I was playing with Haskell and ghci when I found this which really bothers me:
foldl (++) [[3,4,5], [2,3,4], [2,1,1]] []
I expected to get this: [3,4,5,2,3,4,2,1,1]
However it gets:
[[3,4,5],[2,3,4],[2,1,1]]
As far as I understand foldl, it should be this:
(([] ++ [3, 4, 5]) ++ [2, 3, 4]) ++ [2, 1, 1]
If I type this in ghci it really is [3,4,5,2,3,4,2,1,1].
And the other strange thing is this:
Prelude> foldl1 (++) [[3,4,5], [2, 3, 4], [2, 1, 1]]
[3,4,5,2,3,4,2,1,1]
I expect foldl and foldl1 to behave in the same way. So what does foldl actually do?
The order of arguments is wrong. The right one is:
foldl (++) [] [[3,4,5], [2,3,4], [2,1,1]]
(That is, first the accumulator, then the list.)
You switched the arguments around. foldl takes the accumulator's starting value first, then the list to fold. So what happens in your case is that foldl folds over the empty list and thus returns the starting value, which is [[3,4,5], [2, 3, 4], [2, 1, 1]]. This will do what you want:
foldl (++) [] [[3,4,5], [2, 3, 4], [2, 1, 1]]
You got the argument order wrong
Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
Prelude> :t foldl1
foldl1 :: (a -> a -> a) -> [a] -> a
The initial value comes first. In your case, your initial value was [[3,4,5],[2,3,4],[2,1,1]] and you folded over the empty list, so you got back the initial value.
Related
Consider the following function:
(<.>) :: [[a]] -> [[a]] -> [[a]]
xs <.> ys = zipWith (++) xs ys
This essentially takes two two-dimensional arrays of as and concatanates them, left to right, e.x.:
[[1,2],[3,4]] <.> [[1,2],[3,4]] == [[1,2,1,2],[3,4,3,4]]
I would like to be able to write something like the following:
x = foldr1 (<.>) $ repeat [[1,2],[3,4]]
Which should make sense due to Haskell's lazy evaluation, i.e. we should obtain:
x !! 0 == [1,2,1,2,1,2,1,2...]
x !! 1 == [3,4,3,4,3,4,3,4...]
However, when I try to run this example with GHCi, either using foldr1 or foldl1, I either get a non-terminating computation, or a stack overflow.
So my question is:
What's going on here?
Is it possible to do what I'm trying to accomplish here with some function other than foldr1 or foldl1? (I'm happy if I need to modify the implementation of <.>, as long as it computes the same function)
Also, note: I'm aware that for this example, map repeat [[1,2],[3,4]] produces the desired output, but I am looking for a solution that works for arbitrary infinite lists, not just those of the form repeat xs.
I'll expand on what's been said in the comments here. I'm going to borrow (a simplified version of) the GHC version of zipWith, which should suffice for the sake of this discussion.
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f [] _ = []
zipWith f _ [] = []
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
Now, here's what your computation ends up looking like, in it's glorious infinite form.
[[1, 2], [3, 4]] <.> ([[1, 2], [3, 4]] <.> ([[1, 2], [3, 4]] ... ) ... )
Okay, so the top-level is a <.>. Fine. Let's take a closer look at that.
zipWith (++) [[1, 2], [3, 4]] ([[1, 2], [3, 4]] <.> ([[1, 2], [3, 4]] ... ) ... )
Still no problems yet. Now we look at the patterns for zipWith. The first pattern only matches if the left-hand-side is empty. Welp, that's definitely not true, so let's move on. The second only matches if the right-hand-side is empty. So let's see if the right-hand-side is empty. The right-hand-side looks like
[[1, 2], [3, 4]] <.> ([[1, 2], [3, 4]] <.> ([[1, 2], [3, 4]] ... ) ... )
Which is what we started with. So to compute the result, we need access to the result. Hence, stack overflow.
Now, we've established that our problem is with zipWith. So let's play with it. First, we know we're going to be applying this to infinite lists for our contrived example, so we don't need that pesky empty list case. Get rid of it.
-- (I'm also changing the name so we don't conflict with the Prelude version)
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
(<.>) :: [[a]] -> [[a]] -> [[a]]
xs <.> ys = zipWith' (++) xs ys
But that fixes nothing. We still have to evaluate to weak head normal form (read: figure out of the list is empty) to match that pattern.
If only there was a way to do a pattern match without having to get to WHNF... enter lazy patterns. Let's rewrite our function this way.
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f ~(x:xs) ~(y:ys) = f x y : zipWith' f xs ys
Now our function will definitely break if given a finite list. But this allows us to "pretend" pattern match on the lists without actually doing any work. It's equivalent to the more verbose
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' f xs ys = f (head xs) (head ys) : zipWith' f (tail xs) (tail ys)
And now we can test your function properly.
*Main> let x = foldr1 (<.>) $ repeat [[1, 2], [3, 4]]
*Main> x !! 0
[1,2,1,2,1,2,1,2,1,...]
*Main> x !! 1
[3,4,3,4,3,4,3,4,3,...]
The obvious downside of this is that it will definitely fail on finite lists, so you have to have a different function for those.
*Main> [[1, 2], [3, 4]] <.> [[1, 2], [3, 4]]
[[1,2,1,2],[3,4,3,4],*** Exception: Prelude.head: empty list
zipWith is not -- in fact, it can't possibly be -- as lazy as you'd like. Consider this variation on your example:
GHCi> foldr1 (zipWith (++)) [ [[1,2],[3,4]], [] ]
[]
Any empty list of lists in the input will lead to an empty list of lists result. That being so, there is no way to know any of the elements of the result until the whole input has been consumed. Therefore, your function won't terminate on infinite lists.
Silvio Mayolo's answer goes through some potential workarounds for this issue. My suggestion is using non-empty-lists of lists, instead of plain lists of lists:
GHCi> import qualified Data.List.NonEmpty as N
GHCi> import Data.List.NonEmpty (NonEmpty(..))
GHCi> take 10 . N.head $ foldr1 (N.zipWith (++)) $ repeat ([1,2] :| [[3,4]])
[1,2,1,2,1,2,1,2,1,2]
N.zipWith doesn't have to deal with an empty list case, so it can be lazier.
How can I make a function that groups element of a list into lists of predefined length without using explicit recursion.
For example, for 2:
[1, 2, 3, 4, 5, 6, 7, 8]
[[1, 2], [3, 4], [5, 6], [7, 8]]
Thank you!
The following would work (though you may consider it cheating to use groupBy from Data.List)
import Data.Function (on)
import Data.List (groupBy)
group :: Int -> [a] -> [[a]]
group n = map (map snd)
. groupBy ((==) `on` fst)
. zip (enumFrom 1 >>= replicate n)
This is a one-liner if you set your wrap at 100 characters :). I'm guessing you are looking for something that uses a fold.
group :: Int -> [a] -> [[a]]
group n = uncurry (:) . foldr (\x (l,r) -> if length l == n then ([x],l:r)
else (x:l,r))
([],[])
I am relatively new to Haskell so apologies if my question sounds stupid. I have been trying to understand how function composition works and I have come across a problem that I was wondering someone could help me with. I am using map in a function composition in the following two scenarios:
map (*2) . filter even [1,2,3,4]
map (*2) . zipWith max [1,2] [4,5]
Although both the filter and zipWith functions return a list, only the first composition works while the second composition throws the below error:
"Couldn't match expected type '[Int] -> [Int]' with actual type '[c0]'
Any suggestions would be greatly appreciated.
Recall the type of (.).
(.) :: (b -> c) -> (a -> b) -> a -> c
It takes three arguments: two functions and an initial value, and returns the result of the two functions composed.
Now, application of a function to its arguments binds tighter than the (.) operator.
So your expression:
map (*2) . filter even [1,2,3,4]
is parsed as:
(.) (map (*2)) (filter even [1,2,3,4])
now, the first argument, map (*2) is ok. It has type (b -> c), where b and c is Num a => [a]. However, the second argument is a single list:
Prelude> :t filter even [1,2,3,4]
filter even [1,2,3,4] :: Integral a => [a]
and so the type checker will complain that you're passing a [a] as an argument when the (.) function needs a function.
And that's what we see:
Couldn't match expected type `a0 -> [b0]' with actual type `[a1]'
In the return type of a call of `filter'
In the second argument of `(.)', namely `filter even [1, 2, 3, 4]'
In the expression: map (* 2) . filter even [1, 2, 3, 4]
So... parenthesization!
Either use the $ operator to add a parenthesis:
map (*2) . filter even $ [1,2,3,4]
or use explicit parens, removing the composition of two functions
map (*2) (filter even [1,2,3,4])
or even:
(map (*2) . filter even) [1,2,3,4]
The following forms are valid:
map (* 2) $ filter even [1, 2, 3, 4]
(map (* 2) . filter even) [1, 2, 3, 4]
map (* 2) $ zipWith max [1, 2] [4, 5]
(\xs -> map (* 2) . zipWith max xs) [1, 2] [4, 5]
but not the following:
map (* 2) . filter even [1, 2, 3, 4]
map (* 2) . zipWith max [1, 2] [4, 5]
(map (* 2) . zipWith max) [1, 2] [4, 5]
Why is that so? Well, take for example
map (* 2) . zipWith max [1, 2] [4, 5]
it is the same as
(map (* 2)) . (((zipWith max) [1, 2]) [4, 5])
(map (* 2)) has type [Int] -> [Int] (assuming defaulting for Int), (((zipWith max) [1, 2]) [4, 5]) has type [Int] and (.) has type (b -> c) -> (a -> b) -> a -> c or ([Int] -> [Int]) -> ([Int] -> [Int]) -> [Int] -> [Int] in this non-polymorphic case, so this is ill-typed. On the other hand ($) has type (a -> b) -> a -> b, or ([Int] -> [Int]) -> [Int] -> [Int] in this non-polymorphic case, so this:
(map (* 2)) $ (((zipWith max) [1, 2]) [4, 5])
is well-typed.
The result of zipWith max [1,2] [4,5] is a list, not a function. The (.) operator requires a function as its right operand. Hence the error on your second line. Probably what you want is
map (*2) (zipWith max [1,2] [4,5])
Your first example does not compile on WinHugs (Hugs mode); it has the same error. The following will work
(map (*2) . filter even) [1,2,3,4]
as it composes two functions and applies the resulting function to an argument.
Due to the low precedence of (.), Haskell parses
map (*2) . filter even [1,2,3,4]
as
map (*2) . (filter even [1,2,3,4])
i.e. compose map (*2) (a function) with the result of filter even [1,2,3,4] (a list), which makes no sense, and is a type error.
You can fix this using #Theodore's suggestions, or by using ($):
map (*2) . filter even $ [1,2,3,4]
If you check the type of map it is: (a -> b) -> [a] -> [b]
So, it takes a function of a into b and then a list of a and returns a list of b. Right?
Now, you already provide a function of a into b by passing the parameter (*2). So, your partially applied map function end up being: [Integer] -> [Integer] meaning that you will receive a list of integers and return a list of integers.
Up to this point, you could compose (.) a function that has the same signature. If you check what is the type of filter even you would see that it is: [Integer] -> [Integer], as such a valid candidate for composition here.
This composition then, does not alter the final signature of the function, if you check the type of: map (*2) . filter even it is [Integer] -> [Integer]
This would not be the case of the map (*2) . zipWith max [1,2] [4,5] because the zipWith max does not have the same signature as the one expected by map (*2).
A while ago I've asked a question about the function elem here, but I don't think the answer is fully satisfactory. My question is about the expression:
any (`elem` [1, 2]) [1, 2, 3]
We know elem is in a backtick so elem is an infix and my explanation is:
1 `elem` [1, 2] -- True
2 `elem` [1, 2] -- True
3 `elem` [1, 2] -- False
Finally it will return True since it's any rather than all. This looked good until I see a similar expression for isInfixOf:
any (isInfixOf [1, 2, 3]) [[1, 2, 3, 4], [1, 2]]
In this case a plausible explanation seems to be:
isInfixOf [1, 2, 3] [1, 2, 3, 4] -- True
isInfixOf [1, 2, 3] [1, 2] -- False
I wonder why they've been used in such different ways since
any (elem [1, 2]) [1, 2, 3]
will give an error and so will
any (`isInfixOf` [[1, 2, 3, 4], [1, 2]]) [1, 2, 3]
Your problem is with the (** a) syntactic sugar. The thing is that (elem b) is just the partial application of elem, that is:
(elem b) == (\xs -> elem b xs)
However when we use back ticks to make elem infix, we get a special syntax for infix operators which works like this:
(+ a) == (\ b -> b + a)
(a +) == (\ b -> a + b)
So therefore,
(`elem` xs) == (\a -> a `elem` xs) == (\ a -> elem a xs)
while
(elem xs) == (\a -> elem xs a)
So in the latter case your arguments are in the wrong order, and that is what is happening in your code.
Note that the (** a) syntactic sugar works for all infix operators except - since it is also a prefix operator. This exception from the rule is discussed here and here.
Using back-ticks around a function name turns it into an infix operator. So
x `fun` y
is the same as
fun x y
Haskell also has operator sections, f.e. (+ 1) means \x -> x + 1.
So
(`elem` xs)
is the same as
\x -> x `elem` xs
or
\x -> elem x xs
or
flip elem xs
It's called partial application.
isInfixOf [1, 2, 3] returns a function that expects one parameter.
any (elem [1, 2]) [1, 2, 3] is an error because you're looking for an element [1, 2], and the list only contains numbers, so haskell cannot match the types.
I am always interested in learning new languages, a fact that keeps me on my toes and makes me (I believe) a better programmer. My attempts at conquering Haskell come and go - twice so far - and I decided it was time to try again. 3rd time's the charm, right?
Nope. I re-read my old notes... and get disappointed :-(
The problem that made me lose faith last time, was an easy one: permutations of integers.
i.e. from a list of integers, to a list of lists - a list of their permutations:
[int] -> [[int]]
This is in fact a generic problem, so replacing 'int' above with 'a', would still apply.
From my notes:
I code it first on my own, I succeed. Hurrah!
I send my solution to a good friend of mine - Haskell guru, it usually helps to learn from gurus - and he sends me this, which I am told, "expresses the true power of the language, the use of generic facilities to code your needs". All for it, I recently drank the kool-aid, let's go:
permute :: [a] -> [[a]]
permute = foldr (concatMap.ins) [[]]
where ins x [] = [[x]]
ins x (y:ys) = (x:y:ys):[ y:res | res <- ins x ys]
Hmm.
Let's break this down:
bash$ cat b.hs
ins x [] = [[x]]
ins x (y:ys) = (x:y:ys):[ y:res | res <- ins x ys]
bash$ ghci
Prelude> :load b.hs
[1 of 1] Compiling Main ( b.hs, interpreted )
Ok, modules loaded: Main.
*Main> ins 1 [2,3]
[[1,2,3],[2,1,3],[2,3,1]]
OK, so far, so good. Took me a minute to understand the second line of "ins", but OK:
It places the 1st arg in all possible positions in the list. Cool.
Now, to understand the foldr and concatMap. in "Real world Haskell", the DOT was explained...
(f . g) x
...as just another syntax for...
f (g x)
And in the code the guru sent, DOT was used from a foldr, with the "ins" function as the fold "collapse":
*Main> let g=concatMap . ins
*Main> g 1 [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
OK, since I want to understand how the DOT is used by the guru, I try the equivalent expression according to the DOT definition, (f . g) x = f (g x) ...
*Main> concatMap (ins 1 [[2,3]])
<interactive>:1:11:
Couldn't match expected type `a -> [b]'
against inferred type `[[[t]]]'
In the first argument of `concatMap', namely `(ins 1 [[2, 3]])'
In the expression: concatMap (ins 1 [[2, 3]])
In the definition of `it': it = concatMap (ins 1 [[2, 3]])
What!?! Why?
OK, I check concatMap's signature, and find that it needs a lambda and a list, but that's
just a human thinking; how does GHC cope? According to the definition of DOT above...
(f.g)x = f(g x),
...what I did was valid, replace-wise:
(concatMap . ins) x y = concatMap (ins x y)
Scratching head...
*Main> concatMap (ins 1) [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
So... The DOT explanation was apparently
too simplistic... DOT must be somehow clever enough to understand
that we in fact wanted "ins" to get curri-ed away and "eat" the first
argument - thus becoming a function that only wants to operate on [t]
(and "intersperse" them with '1' in all possible positions).
But where was this specified? How did GHC knew to do this, when we invoked:
*Main> (concatMap . ins) 1 [[2,3]]
[[1,2,3],[2,1,3],[2,3,1]]
Did the "ins" signature somehow conveyed this... "eat my first argument" policy?
*Main> :info ins
ins :: t -> [t] -> [[t]] -- Defined at b.hs:1:0-2
I don't see nothing special - "ins" is a function that takes a 't',
a list of 't', and proceeds to create a list with all "interspersals". Nothing about "eat your first argument and curry it away".
So there... I am baffled. I understand (after an hour of looking at the code!) what goes on, but... God almighty... Perhaps GHC makes attempts to see how many arguments it can "peel off"?
let's try with no argument "curried" into "ins",
oh gosh, boom,
let's try with one argument "curried" into "ins",
yep, works,
that must be it, proceed)
Again - yikes...
And since I am always comparing the languages I am learning with what I already know, how would "ins" look in Python?
a=[2,3]
print [a[:x]+[1]+a[x:] for x in xrange(len(a)+1)]
[[1, 2, 3], [2, 1, 3], [2, 3, 1]]
Be honest, now... which is simpler?
I mean, I know I am a newbie in Haskell, but I feel like an idiot... Looking at 4 lines of code for an hour, and ending up assuming that the compiler... tries various interpretations until it finds something that "clicks"?
To quote from Lethal weapon, "I am too old for this"...
(f . g) x = f (g x)
This is true. You concluded from that that
(f . g) x y = f (g x y)
must also be true, but that is not the case. In fact, the following is true:
(f . g) x y = f (g x) y
which is not the same.
Why is this true? Well (f . g) x y is the same as ((f . g) x) y and since we know that (f . g) x = f (g x) we can reduce that to (f (g x)) y, which is again the same as f (g x) y.
So (concatMap . ins) 1 [[2,3]] is equivalent to concatMap (ins 1) [[2,3]]. There is no magic going on here.
Another way to approach this is via the types:
. has the type (b -> c) -> (a -> b) -> a -> c, concatMap has the type (x -> [y]) -> [x] -> [y], ins has the type t -> [t] -> [[t]]. So if we use concatMap as the b -> c argument and ins as the a -> b argument, then a becomes t, b becomes [t] -> [[t]] and c becomes [[t]] -> [[t]] (with x = [t] and y = [t]).
So the type of concatMap . ins is t -> [[t]] -> [[t]], which means a function taking a whatever and a list of lists (of whatevers) and returning a list of lists (of the same type).
I'd like to add my two cents. The question and answer make it sound like . is some magical operator that does strange things with re-arranging function calls. That's not the case. . is just function composition. Here's an implementation in Python:
def dot(f, g):
def result(arg):
return f(g(arg))
return result
It just creates a new function which applies g to an argument, applies f to the result, and returns the result of applying f.
So (concatMap . ins) 1 [[2, 3]] is saying: create a function, concatMap . ins, and apply it to the arguments 1 and [[2, 3]]. When you do concatMap (ins 1 [[2,3]]) you're instead saying, apply the function concatMap to the result of applying ins to 1 and [[2, 3]] - completely different, as you figured out by Haskell's horrendous error message.
UPDATE: To stress this even further. You said that (f . g) x was another syntax for f (g x). This is wrong! . is just a function, as functions can have non-alpha-numeric names (>><, .., etc., could also be function names).
You're overthinking this problem. You can work it all out using simple equational reasoning. Let's try it from scratch:
permute = foldr (concatMap . ins) [[]]
This can be converted trivially to:
permute lst = foldr (concatMap . ins) [[]] lst
concatMap can be defined as:
concatMap f lst = concat (map f lst)
The way foldr works on a list is that (for instance):
-- let lst = [x, y, z]
foldr f init lst
= foldr f init [x, y, z]
= foldr f init (x : y : z : [])
= f x (f y (f z init))
So something like
permute [1, 2, 3]
becomes:
foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1
((concatMap . ins) 2
((concatMap . ins) 3 [[]]))
Let's work through the first expression:
(concatMap . ins) 3 [[]]
= (\x -> concatMap (ins x)) 3 [[]] -- definition of (.)
= (concatMap (ins 3)) [[]]
= concatMap (ins 3) [[]] -- parens are unnecessary
= concat (map (ins 3) [[]]) -- definition of concatMap
Now ins 3 [] == [3], so
map (ins 3) [[]] == (ins 3 []) : [] -- definition of map
= [3] : []
= [[3]]
So our original expression becomes:
foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1
((concatMap . ins) 2
((concatMap . ins) 3 [[]]))
= (concatMap . ins) 1
((concatMap . ins) 2 [[3]]
Let's work through
(concatMap . ins) 2 [[3]]
= (\x -> concatMap (ins x)) 2 [[3]]
= (concatMap (ins 2)) [[3]]
= concatMap (ins 2) [[3]] -- parens are unnecessary
= concat (map (ins 2) [[3]]) -- definition of concatMap
= concat (ins 2 [3] : [])
= concat ([[2, 3], [3, 2]] : [])
= concat [[[2, 3], [3, 2]]]
= [[2, 3], [3, 2]]
So our original expression becomes:
foldr (concatMap . ins) [[]] [1, 2, 3]
= (concatMap . ins) 1 [[2, 3], [3, 2]]
= (\x -> concatMap (ins x)) 1 [[2, 3], [3, 2]]
= concatMap (ins 1) [[2, 3], [3, 2]]
= concat (map (ins 1) [[2, 3], [3, 2]])
= concat [ins 1 [2, 3], ins 1 [3, 2]] -- definition of map
= concat [[[1, 2, 3], [2, 1, 3], [2, 3, 1]],
[[1, 3, 2], [3, 1, 2], [3, 2, 1]]] -- defn of ins
= [[1, 2, 3], [2, 1, 3], [2, 3, 1],
[1, 3, 2], [3, 1, 2], [3, 2, 1]]
Nothing magical here. I think you may have been confused because it's easy to assume that concatMap = concat . map, but this is not the case. Similarly, it may seem like concatMap f = concat . (map f), but this isn't true either. Equational reasoning will show you why.