I am from python world, but try to use functional as much as possible, and change my imperative thinking.
Now i study haskell and found that
list = [(x,y) | x<-[1,2,3], y<-[4,5,6]]
are translated to
list' =
[1,2,3] >>= \x ->
[4,5,6] >>= \y ->
return (x,y)
I try to understand step by step processing of list monad binds chain:
bind defind as:
xs >>= f = concat (map f xs)
and bind is left associative
So as I understend, at start first bind ([1,2,3] >>= \x -> [4,5,6]) executed with result [4,5,6,4,5,6,4,5,6]
And then next bind
[4,5,6,4,5,6,4,5,6] >>= \y -> return (x,y) executed
But how it can see x inside lambda if it's allready calculated ?? x is just argument that has no concrete value at all (lambda can be call with varios arguments at any time, how can we se it outside and fixed??). If it somehow can see it how can it know about that x call history was changed with 1,2,3 ? in my understanding onces first bind calculation done, only result [4,5,6,4,5,6,4,5,6] avaible and it goes next, to first argument of next bind.
So I can't understand how can i read this construction, and how it step by step logicaly produce correct result?
This is a common source of confusion. The scope of the lambdas extends as far as possible, so this:
[1,2,3] >>= \x ->
[4,5,6] >>= \y ->
return (x,y)
Is equivalent to this:
[1,2,3] >>= (\x ->
[4,5,6] >>= (\y ->
return (x,y)))
So the inner lambda \y -> … is inside the scope of the outer lambda, \x -> …, meaning x and y are both in scope. You can then inline the definitions of >>= and return for the [] monad instance and step through the evaluation:
concatMap (\x ->
concatMap (\y ->
[(x,y)]) [4,5,6]) [1,2,3]
concat
[ concatMap (\y -> [(1,y)]) [4,5,6]
, concatMap (\y -> [(2,y)]) [4,5,6]
, concatMap (\y -> [(3,y)]) [4,5,6]
]
concat
[ concat [[(1,4)], [(1,5)], [(1,6)]]
, concat [[(2,4)], [(2,5)], [(2,6)]]
, concat [[(3,4)], [(3,5)], [(3,6)]]
]
concat
[ [(1,4), (1,5), (1,6)]
, [(2,4), (2,5), (2,6)]
, [(3,4), (3,5), (3,6)]
]
[ (1,4), (1,5), (1,6)
, (2,4), (2,5), (2,6)
, (3,4), (3,5), (3,6)
]
A common and more succinct way of expressing this is with the Applicative instance instead of the Monad instance, using the <$> (fmap) and <*> (ap) operators or liftA2:
(,) <$> [1,2,3] <*> [4,5,6]
liftA2 (,) [1,2,3] [4,5,6]
Related
Reading the Monad chapter in "Programming in Haskell" 2nd ed. from Graham Hutton, I found this example on page 167 to illustrate the behaviour of the List Monad:
> pairs [1,2] [3,4]
[(1,3),(1,4),(2,3),(2,4)]
With pairs defined like this:
pairs :: [a] -> [b] -> [(a,b)]
pairs xs ys = do x <- xs
y <- ys
return (x,y)
And this implementation of bind:
instance Monad [] where
-- (>>=) :: [a] -> (a -> [b]) -> [b]
xs >>= f = [y | x <- xs, y <- f x]
I tried to understand with pencil and paper how the example worked out, but didn't get it.
Then I found, that in other books the bind operation is defined differently:
...
xs >>= f = concat (fmap f xs)
With this definition I understand why the example works.
But the first definition is the one I found on hackage in the prelude, so I trust its correct.
My question:
Can anybody explain why the first definition is equivalent to the second? (Where does the concat-stuff happen in the first one?)
List comprehensions are just syntactic sugar. Basically, [f x y | x<-l, y<-m] is sugar for
concatMap (\x -> concatMap (\y -> return $ f x y) m) l
or equivalently
concat $ fmap (\x -> concat $ fmap (\y -> return $ f x y) m) l
thus the two implementations are indeed equivalent by definition.
Anyway you can of course manually evaluate the example from the comprehension-based definition, using “intuitive set comprehension” evaluation:
pairs [1,2] [3,4]
≡ do { x <- [1,2]; y <- [3,4]; return (x,y) }
≡ [1,2] >>= \x -> [3,4] >>= \y -> return (x,y)
≡ [p | x<-[1,2], p <- (\ξ -> [3,4] >>= \y -> return (ξ,y)) x]
≡ [p | x<-[1,2], p <- ([3,4] >>= \y -> return (x,y))]
≡ [p | x<-[1,2], p <- [q | y<-[3,4], q <- (\υ -> return (x,υ)) y]]
≡ [p | x<-[1,2], p <- [q | y<-[3,4], q <- return (x,y)]]
≡ [p | x<-[1,2], p <- [q | y<-[3,4], q <- [(x,y)]]]
≡ [p | x<-[1,2], p <- [(x,3), (x,4)]]
≡ [(1,3), (1,4)] ++ [(2,3), (2,4)]
≡ [(1,3), (1,4), (2,3), (2,4)]
[y | x <- xs, y <- f x] takes all the xs in xs one-by-one and
apply f to them, which is a monadic action a -> [a], thus the result is a list of values ([a])
the comprehension proceeds to address each y in f x one-by-one
each y is sent to the output list
this is equivalent to first mapping f over each of the elements of the input list, resulting in a list of nested lists, that are then concatenated. Notice that fmap is map for lists, and you could use concatMap f xs as the definition of xs >>= f.
I'm currently preparing for my final exam regarding Haskell, and I am going over the Monads and we were giving an example such as:
Given the following definition for the List Monad:
instance Monad [] where
m >>= f = concatMap f m
return x = [x]
where the types of (>>=) and concatMap are
(>>=) :: [a] -> (a -> [b]) -> [b]
concatMap :: (a -> [b]) -> [a] -> [b]
What is the result of the expression?
> [1,2,3] >>= \x -> [x..3] >>= \y -> return x
[1, 1, 1, 2, 2, 3] //Answer
Here the answer is different from what I thought it to be, now we briefly went over Monads, but from what I understand (>>=) is called bind and could be read in the expression above as "applyMaybe". In this case for the first part of bind we get [1,2,3,2,3,3] and we continue to the second part of the bind, but return x is defined to return the list of x. Which should have been [1,2,3,2,3,3]. However, I might have misunderstood the expression. Can anyone explain the wrong doing of my approach and how should I have tackled this. Thanks.
this case for the first part of bind we get [1,2,3,2,3,3]
Correct.
and we continue to the second part of the bind, but "return x" is defined to return the list of x. Which should have been [1,2,3,2,3,3].
Note that, in...
[1,2,3] >>= \x -> [x..3] >>= \y -> return x
... x is bound by (the lambda of) the first (>>=), and not by the second one. Some extra parentheses might make that clearer:
[1,2,3] >>= (\x -> [x..3] >>= (\y -> return x))
In \y -> return x, the values bound to y (that is, the elements of [1,2,3,2,3,3]) are ignored, and replaced by the corresponding values bound to x (that is, the elements of the original list from which each y was generated). Schematically, we have:
[1, 2, 3] -- [1,2,3]
[1,2,3, 2,3, 3] -- [1,2,3] >>= \x -> [x..3]
[1,1,1, 2,2, 3] -- [1,2,3] >>= \x -> [x..3] >>= \y -> return x
First, let's be clear how this expression is parsed: lambdas are syntactic heralds, i.e. they grab as much as they can to their right, using it as the function result. So what you have there is parsed as
[1,2,3] >>= (\x -> ([x..3] >>= \y -> return x))
The inner expression is actually written more complicated than it should be. y isn't used at all, and a >>= \_ -> p can just be written as a >> p. There's an even better replacement though: generally, the monadic bind a >>= \q -> return (f q) is equivalent to fmap f a, so your expression should really be written
[1,2,3] >>= (\x -> (fmap (const x) [x..3]))
or
[1,2,3] >>= \x -> map (const x) [x..3]
or
[1,2,3] >>= \x -> replicate (3-x+1) x
At this point it should be pretty clear what the result will be, since >>= in the list monad simply maps over each element and concatenates the results.
Operation >> description is the following:
Sequentially compose two actions, discarding any value produced by the
first, like sequencing operators (such as the semicolon) in imperative
languages.
Here is the example which confuses me:
> ([1] ++ [2]) >> ([2] ++ [3])
[2,3,2,3]
I'm expecting the list [2,3] which would be result of right part of expression. How can result of [2,3,2,3] be explained?
(>>) is by default defined as
a >> b = a >>= (\_ -> b)
so the value being ignored is an a in a given monadic value m a. The type of >>= specialised to list is:
(>>=) :: [a] -> (a -> [b]) -> [b]
l >>= f invokes f for each element of the list l to product a list of lists which is then concatenated.
e.g.
[1,2] >>= (\i -> [i, -i])
> [1,-1,2,-2]
Ignoring each input element and returning the value [2,3] will result in n copies of the list [2,3] for an input list of length n
e.g.
[1] >>= (\_ -> [2,3])
> [2,3]
[1,2] >>= (\_ -> [2,3])
> [2,3,2,3]
this second example is equivalent to ([1] ++ [2]) >> ([2] ++ [3]) in your question.
A small complement to the answer by Lee:
([1] ++ [2]) >> ([2] ++ [3])
is equivalent to
([1] ++ [2]) >> ([2] ++ [3]) >>= \x -> return x
which is equivalent to
([1] ++ [2]) >>= \y -> ([2] ++ [3]) >>= \x -> return x
which is equivalent to
[ x | y <- [1]++[2] , x <- [2]++[3] ]
which is close to the imperative pseudocode
for y in [1]++[2]:
for x in [2]++[3]:
print x
I want to verify following implementation of foldl in terms foldr is correct:
foldl4 = foldr . flip
I used following tests in HUGS:
foldl4 (+) 3 []
foldl4 (+) 3 [1,2,3]
They worked.
Please suggest any more tests I could do.
Thanks
here is a simple test: foldl (flip (:)) [] should be reverse...
if you want to test foldr vs foldl you probably should not use commutative operations ;)
here is some proof straight from GHCi:
λ> foldl (flip (:)) [] [1..5]
[5,4,3,2,1]
λ> foldl4 (flip (:)) [] [1..5]
[1,2,3,4,5]
and as flip (+) = (+) you can guess straight from your definition:
foldl4 (+) y xs
{ def }
= foldr (flip (+)) y xs
{ flip (+) = (+) }
= foldr (+) y xs
if you want some hint of how to do foldl with foldr: you should use functions for the accumulator/state/b part of foldr :: (a -> b -> b) -> b -> [a] -> b - think of continuation passing and try to replace the : in
x : (y : (z : [])
with some smart function to get
((b `f` x) `f` y) `f` z
remember you want to mimick
foldl f b [x,y,z] = ((b `f` x) `f` y) `f` z
with foldr which basically replaces : with it's first parameter and [] with it's second if you pass [x,y,z] as the 3rd:
foldr f' b' [x,y,z] = x `f'` (y `f'` (z `f'` b'))
and you now want to shift the parens
Those two are not the same. foldl and foldr do semantically different things, but flip only induces a syntactic difference, so foldr . flip cannot ever ever be foldl.
Something that is foldl for example (on finite lists) is
foldl5 = (.) (. reverse) . foldr . flip
That first part might look confusing, but it basically applies reverse to the third argument rather than the first.
I found precedence and associativity is a big obstacle for me to understand what the grammar is trying to express at first glance to haskell code.
For example,
blockyPlain :: Monad m => m t -> m t1 -> m (t, t1)
blockyPlain xs ys = xs >>= \x -> ys >>= \y -> return (x, y)
By experiment, I finally got it means,
blockyPlain xs ys = xs >>= (\x -> (ys >>= (\y -> return (x, y))))
instead of
blockyPlain xs ys = xs >>= (\x -> ys) >>= (\y -> return (x, y))
Which works as:
*Main> blockyPlain [1,2,3] [4,5,6]
[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]
I can get info from ghci for (>>=) as an operator, (infixl 1 >>=).
But there's no information for -> since it's not an operator.
Could someone of you guys give some reference to make this grammar thing easier to grasp?
The rule for lambdas is pretty simple: the body of the lambda extends as far to the right as possible without hitting an unbalanced parenthesis.
f (\x -> foo (bar baz) *** quux >>= quuxbar)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
body
A good rule of thumb seems to be that you can never make a custom operator that has precedence over built in syntactic constructs. For instance consider this example:
if b then f *** x else f *** y
Regardless of the associativity of ***, no one would expect it to binds as:
(if b then f *** x else f) *** y
There aren't a lot of syntactic constructs in Haskell (do and case are a little special because of layout syntax) but let can be used as another example:
(let x = y in y *** x) /= ((let x = y in y) *** x)