What is wrong with this list comprehension code? - haskell

My aim is to list all elements of the array a whose values are greater than their index positions. I wrote a Haskell code like this.
[a|i<-[0..2],a<-[1..3],a!!i>i]
When tested on ghci prelude prompt, I get the following error message which I am unable to understand.
No instance for (Num [a]) arising from the literal 3 at <interactive>:1:20 Possible fix: add an instance declaration for (Num [a])

Given the expression a!!i, Haskell will infer that a is a list (i.e. a::[a]). Given the expression a<-[1..3], Haskell will infer that a will have type Num a => a (because you are drawing a from a list of Num a => a values). Trying to unify these types, Haskell concludes that a must actually be of type Num a => [a].
The bottom line is that it doesn't make sense to treat a as a list in one context and as an element from a list of numbers in another context.
EDIT
I'm thinking you could do what you want with something like this:
f xs = map fst . filter (uncurry (>)) $ (xs `zip` [0..])
The expression xs `zip` [0..] creates a list of pairs, where the first value in each pair is drawn from xs and the second value from [0..] (an infinite list starting from 0). This serves to associate an index to each value in xs. The expression uncurry (>) converts the < operator into a function that works on pairs. So the expression filter (uncurry (>)) filters a list of pairs to only those elements where the first value is greater than the second. Finally, map fst applies the fst function to each pair of values and returns the result as a list (the fst function returns the first value of a pair).
EDIT 2
Writing pointless code is fun, and so I give you:
f = map snd . filter (uncurry (<)) . zip [0..]

import Data.Maybe
import Control.Monad
f = catMaybes . zipWith (mfilter.(<)) [0..] . map Just
Disclaimer: The given code was not proof read and may have been made outside of sobriety. The author has little recollection of what it is about.

Related

How to incorporate $ in a given expression?

I want to write an expression which will give a list that is equal to the list comprehension [x|x<-[1..100], x`mod`7==0], but I'm asked by my teacher to use $ in this program.
So, how could I use $ in here?
PS: I'm new to Haskell, so would prefer easy expressions, please.
($) is in an infix operator with a type signature
($) :: (a -> b) -> a -> b
which means it takes two parameters, first a function (a -> b) (on the left) which accepts a single parameter, a value of type designated by the type variable a. The second parameter of ($) (on the right) is a single value again designated by the type variable a. Then the ($) operator simply applies it's second parameter to the first parameter. So for an example (+2) $ 3 would give us 5.
So if you insist on doing list comprehensions you may do as follows in point-free style;
Prelude> [x|x<-[1..100], (== 0) . mod x $ 7]
[7,14,21,28,35,42,49,56,63,70,77,84,91,98]
or in a more straightforward fashion
Prelude> filter ((==0) . (`mod` 7)) $ take 100 [1..]
[7,14,21,28,35,42,49,56,63,70,77,84,91,98]
$ just means "take whatever is on the right, and pass it as argument to the left".
So for example :
map (`mod`7) (take 100 [1..])
map (`mod`7) $ take 100 [1..]
Those two lines are the same, the $ just means you can avoid the parenthesis around the second call.
The take is useless but I didn't have a better idea for a simple example :)

parenthesis in Haskell functions

I just want to know how do we know which functions need brackets () and which ones do not? For example
replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
works fine. But
replicate 100 (product (map (*3) (zipWith (max [1,2,3,4,5] [4,5,6,7,8]))))
does not work. It is because I put a set of brackets for zipWith. In this small example, zipWith and max do not have brackets, but replicate, product and map do. In general is there a way to know/figure out which functions need brackets and which ones dont.
Function application is left associative. So, when you write an expression like:
f g h x
it means:
((f g) h) x
And also the type of zipWith provides a clue:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
it says that zipWith has 3 parameters: a function and two lists.
When you write:
zipWith (max [1,2,3,4,5] [4,5,6,7,8])
The interpreter will understand that
max [1,2,3,4,5] [4,5,6,7,8]
will be the first parameter to zipWith, which is type incorrect. Note that zipWith expects a function of two arguments as its first argument and, as pointed out by #Cubic, max [1,2,3,4,5] [4,5,6,7,8] will return the maximum
between these two lists according the usual lexicographic order, which will be of type [a], for some type a which is instance of Ord and Num. Said that, the error become evident since you are trying to pass a value of type
(Num a, Ord a) => [a]
where a value of type
(a -> b -> c)
is expected.
Rodrigo gave the right answer. I'll just add that it is a misconception to think that some functions need parentheses, while others don't.
This is just like in school math:
3 * (4+5)
It is simply not the case that + expressions need parentheses and * expressions don't need them in general.
In Haskell, you can always get away without parentheses at all. Whenever you need to enclose an expression in parentheses, the alternative is to introduce a local name and bind it to that expression, then use the name instead of the expression.
In your example:
replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
let list1 = product list2
list2 = map thrice list3
thrice x = x*3
list3 = zipWith max [1,2,3,4,5] [4,5,6,7,8]
in replicate 100 list1
In fact, I often write functions top down thus:
foo x y z = result
where
result = ...
...
However, as it was said before, expressions that consist of function applications can also often be written without parentheses by making use of (.) and ($) and in such cases, the top down approach from above may be overly verbose and the following would be much clearer (because there is no noise through newly introduced names):
replicate 100
. product
. map (*3)
$ zipWith max [1..5] [4..8]

Haskell, pattern-matching on lists to get every first element of tuples with arbitrary length

I want to get the first element of every tuple stored in a list like so:
INPUT : [(1,2,3), (1,4,5), (1,6,7)]
Wanted OUTPUT : [(1,1,1)] % Note the tuple notation
This is the function I have written so far:
f [] = []
f ((x,y,z):xs) = x:(f xs)
But it gives me this output:
[1,1,1]
instead of
[(1,1,1)]
Where is my misunderstanding?
As yet stated in the comment by #pdexter, you cannot create a tuple with arbitrary length. So what you're trying to do will only work when the tuple exactly pattern matches a tuple with 3 Ints. Let me show you an example to clarify what I mean:
helper :: [(Int,Int,Int)] -> (Int,Int,Int)
helper xs = (x,y,z)
where [x,y,z] = f xs
f :: [(Int,Int,Int)] -> [Int]
f [] = []
f ((x,y,z):xs) = x : (f xs)
Here we manage to create (x,y,z) by pattern matching on [x,y,z], but what if there were more than three tuples, our pattern matching would no longer be valid?
So you should ask yourself the question what it is you're really trying to accomplish with this code and what scenarios might occur (e.g.: empty tuples, tuples with varying lengths mutually, .. ?) and also, how should your program handle these different cases?
If there is no functional reason as to why you like the output to be in a tuple, I suggest you keep the function as is.
Good luck!

Print elements of list that are repeated in Haskell

I want to print those elements that appear more than once in the list. can you please tell me how can I do that.. I am new to haskell.
for example if I have [1,2,3,3,2,4,5,6,5] that i want to get only [2,3,5] because these are the repeated elements in list.
Another solution: First sort the list, then group equal elements and take only the ones that appear multiple times:
>>> :m + Data.Maybe Data.List
>>> let xs = [1..100000] ++ [8,18..100] ++ [10,132,235]
>>> let safeSnd = listToMaybe . drop 1
>>> mapMaybe safeSnd $ group $ sort xs
[8,10,18,28,38,48,58,68,78,88,98,132,235]
group $ sort xs is a list of lists where each list contains all equal elements.
mapMaybe safe2nd returns only those lists that have a 2nd element (= the orignal element occured more than once in the orginal list).
This is method should be faster than the one using nub, especially for large lists.
Data.Map.Lazy and Data.Map.Strict are host to a bunch of interesting functions for constructing maps (association maps, dictionaries, whatever you want to call them). One of them is fromListWith
fromListWith :: Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
What you want to build is a map that tells you, for each value in your input list, how often it occurs. The values would be the keys of the map (type k), their counts would be the values associated with the keys (type a). You could use the following expression for that:
fromListWith (+) . map (\x -> (x, 1))
First, all values in the list are put into a tuple, together with a count of one. Then, fromListWith builds a map from the list; if a key already exists, it computes a new count using (+).
Once you've done this, you're only interested in the elements that occur more than once. For this, you can use filter (> 1) from Data.Map.
Finally, you just want to know all keys that remain in the map. Use the function keys for this.
In the end, you get the following module:
import qualified Data.Map.Strict as M
findDuplicates :: (Ord a) => [a] -> [a]
findDuplicates
= M.keys
. M.filter (> 1)
. M.fromListWith (+)
. map (\x -> (x, 1 :: Integer))
It's common practice to import certain packages like Data.Map qualified, to avoid name conflicts between modules (e.g. filter from Data.Map and the one from Prelude are very different). In this situation, it's best to choose Data.Map.Strict; see the explanation at the top of Data.Map.
The complexity of this method should be O(n log n).
I thought it could be optimized by using a boolean flag to indicate that the value is a duplicate. However, this turned out to be about 20% slower.
You're basically looking for the list of elements that are not unique, or in other words, the difference between the original list and the list of unique elements. In code:
xs \\ (nub xs)
If you don't want to have duplicates in the result list, you'll want to call nub again:
nub $ xs \\ (nub xs)

Haskell: Minimum sum of list

So, I'm new here, and I would like to ask 2 questions about some code:
Duplicate each element in list by n times. For example, duplicate [1,2,3] should give [1,2,2,3,3,3]
duplicate1 xs = x*x ++ duplicate1 xs
What is wrong in here?
Take positive numbers from list and find the minimum positive subtraction. For example, [-2,-1,0,1,3] should give 1 because (1-0) is the lowest difference above 0.
For your first part, there are a few issues: you forgot the pattern in the first argument, you are trying to square the first element rather than replicate it, and there is no second case to end your recursion (it will crash). To help, here is a type signature:
replicate :: Int -> a -> [a]
For your second part, if it has been covered in your course, you could try a list comprehension to get all differences of the numbers, and then you can apply the minimum function. If you don't know list comprehensions, you can do something similar with concatMap.
Don't forget that you can check functions on http://www.haskell.org/hoogle/ (Hoogle) or similar search engines.
Tell me if you need a more thorough answer.
To your first question:
Use pattern matching. You can write something like duplicate (x:xs). This will deconstruct the first cell of the parameter list. If the list is empty, the next pattern is tried:
duplicate (x:xs) = ... -- list is not empty
duplicate [] = ... -- list is empty
the function replicate n x creates a list, that contains n items x. For instance replicate 3 'a' yields `['a','a','a'].
Use recursion. To understand, how recursion works, it is important to understand the concept of recursion first ;)
1)
dupe :: [Int] -> [Int]
dupe l = concat [replicate i i | i<-l]
Theres a few problems with yours, one being that you are squaring each term, not creating a new list. In addition, your pattern matching is off and you would create am infinite recursion. Note how you recurse on the exact same list as was input. I think you mean something along the lines of duplicate1 (x:xs) = (replicate x x) ++ duplicate1 xs and that would be fine, so long as you write a proper base case as well.
2)
This is pretty straight forward from your problem description, but probably not too efficient. First filters out negatives, thewn checks out all subtractions with non-negative results. Answer is the minumum of these
p2 l = let l2 = filter (\x -> x >= 0) l
in minimum [i-j | i<-l2, j<-l2, i >= j]
Problem here is that it will allow a number to be checkeed against itself, whichwiull lend to answers of always zero. Any ideas? I'd like to leave it to you, commenter has a point abou t spoon-feeding.
1) You can use the fact that list is a monad:
dup = (=<<) (\x -> replicate x x)
Or in do-notation:
dup xs = do x <- xs; replicate x x; return x
2) For getting only the positive numbers from a list, you can use filter:
filter (>= 0) [1,-1,0,-5,3]
-- [1,0,3]
To get all possible "pairings" you can use either monads or applicative functors:
import Control.Applicative
(,) <$> [1,2,3] <*> [1,2,3]
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
Of course instead of creating pairs you can generate directly differences when replacing (,) by (-). Now you need to filter again, discarding all zero or negative differences. Then you only need to find the minimum of the list, but I think you can guess the name of that function.
Here, this should do the trick:
dup [] = []
dup (x:xs) = (replicate x x) ++ (dup xs)
We define dup recursively: for empty list it is just an empty list, for a non empty list, it is a list in which the first x elements are equal to x (the head of the initial list), and the rest is the list generated by recursively applying the dup function. It is easy to prove the correctness of this solution by induction (do it as an exercise).
Now, lets analyze your initial solution:
duplicate1 xs = x*x ++ duplicate1 xs
The first mistake: you did not define the list pattern properly. According to your definition, the function has just one argument - xs. To achieve the desired effect, you should use the correct pattern for matching the list's head and tail (x:xs, see my previous example). Read up on pattern matching.
But that's not all. Second mistake: x*x is actually x squared, not a list of two values. Which brings us to the third mistake: ++ expects both of its operands to be lists of values of the same type. While in your code, you're trying to apply ++ to two values of types Int and [Int].
As for the second task, the solution has already been given.
HTH

Resources