The code for concat:
concat :: [[a]] -> [a]
concat xss = [x | xs <- xss, x <- xs]
I don't understand how it is being read. How does xss get split into xs and x? Or am I misreading it?
For example, given:
concat [[1,2,3],[4],[5]]
how is [1,2,3,4,5] achieved?
Inside a list comprehension, the bit a <- b means "for each a in b".
So in your case, xs <- xss should read like "for each xs in xss", and then x <- xs should read like "for each x in xs", which is also valid becase xs itself is a list, because xss is a list of lists.
So as the list comprehension unfolds, xs becomes bound first to [1,2,3], then to [4], and then to [5], and within each iteration of xs, x becomes bound to 1, 2, 3, then to 4, and finally to 5.
If we had to make a comparison with imperative programming, we can think of
[ expr | x1 <- list1 , x2 <- list2 , ....]
as a nested for loop accumulating the values resulting from expr in a list, as follows:
result = []
for x1 in list1:
for x2 in list2:
...
result.append(expr)
In you case, we have
result = []
for xs in xss:
for x in xs:
result.append(x)
So, when xss = [[1,2,3],[4],[5]] we have:
xs = [1,2,3]
x = 1 gets appended to the result
x = 2 gets appended to the result
x = 3 gets appended to the result
xs = [4]
x = 4 gets appended to the result
xs = [5]
x = 5 gets appended to the result
The final result is therefore [1,2,3,4,5].
This comparison is not a completely faithful description, since it does not take laziness into account, and Haskell does not really compute the final list by appending data to a mutable list as done above. Perhaps Python's yield and generators would be closer. Still, the comparison above should illustrate the basic mechanism.
Well with the obvious identities,
[ E | P <- (xs ++ ys), Q ] === [ E | P <- xs, Q ] ++ [ E | P <- ys, Q ]
[ x | xs <- [E], x <- xs ] === [ x | x <- E ]
[ x | x <- [E] ] === [E]
we can just follow the code,
concat [[1,2,3], [4], [5]]
= {- by definition of `concat` -}
[x | xs <- [[1,2,3], [4], [5]], x <- xs]
= {- by definition of `++` -}
[x | xs <- [[1,2,3]] ++ [[4], [5]], x <- xs]
= {- by the first identity -}
[x | xs <- [[1,2,3]], x <- xs] ++ [x | xs <- [[4], [5]], x <- xs]
= {- by the second identity -}
[x | x <- [1,2,3] ] ++ [x | xs <- [[4], [5]], x <- xs]
= {- by definition of `++` -}
[x | x <- [1,2,3] ] ++ [x | xs <- [[4]] ++ [[5]], x <- xs]
= {- by the first identity -}
[x | x <- [1,2,3]] ++ [x | xs <- [[4]], x <- xs] ++ [x | xs <- [[5]], x <- xs]
= {- by the second identity -}
[x | x <- [1,2,3]] ++ [x | x <- [4] ] ++ [x | x <- [5] ]
= {- and by the third -}
[x | x <- [1,2,3]] ++ [ 4 ] ++ [ 5 ]
= {- repeating as before -}
[x | x <- [1]] ++ [x | x <- [2]] ++ [x | x <- [3]] ++ [4] ++ [ 5 ]
= {- by the third identity -}
[ 1 ] ++ [ 2 ] ++ [ 3 ] ++ [4] ++ [ 5 ]
= {- by definition of `++` -}
[ 1 , 2 , 3 , 4 , 5 ]
Thus concat, when applied to a list of lists, has the effect of "opening up" and eliminating the inner parentheses in it.
In the process we have also discovered another identity,
[ x | x <- Q ] === Q
which follows from the ones above and the properties of ++, where
[A,B,C,...,Z] === [A] ++ [B] ++ [C] ++ ... ++ [Z]
See also:
An introduction to the theory of lists. Technical Monograph PRG-56, R.S. Bird 1986.
Related
In order to understand Monad, I came up with the following definitions:
class Applicative' f where
purea :: a -> f a
app :: f (a->b) -> f a -> f b
class Applicative' m => Monadd m where
(>>|) :: m a -> (a -> m b) -> m b
instance Applicative' [] where
purea x = [x]
app gs xs = [g x | g <- gs, x <- xs]
instance Monadd [] where
(>>|) xs f = [ y | x <-xs, y <- f x]
It works as expected:
(>>|) [1,2,3,4] (\x->[(x+1)])
[2,3,4,5]
I am not sure how it is working though.
For example:
[ y | y <- [[1],[2]]]
[[1],[2]]
How does application (\x->([x+1]) to each list element of [1,2,3] result in [2,3,4] and not [[2],[3],[4]]
Or quite simply my confusion seems to stem from not understanding how this statement [ y | x <-xs, y <- f x] actually works
Wadler, School of Haskell, LYAH, HaskellWiki, Quora and many more describe the list monad.
Compare:
(=<<) :: Monad m => (a -> m b) -> m a -> m b for lists with
concatMap :: (a -> [b]) -> [a] -> [b] for m = [].
The regular (>>=) bind operator has the arguments flipped, but is otherwise just an infix concatMap.
Or quite simply my confusion seems to stem from not understanding how this statement actually works:
(>>|) xs f = [ y | x <- xs, y <- f x ]
Since list comprehensions are equivalent to the Monad instance for lists, this definition is kind of cheating. You're basically saying that something is a Monadd in the way that it's a Monad, so you're left with two problems: Understanding list comprehensions, and still understanding Monad.
List comprehensions can be de-sugared for a better understanding:
Removing syntactic sugar: List comprehension in Haskell
In your case, the statement could be written in a number of other ways:
Using do-notation:
(>>|) xs f = do x <- xs
y <- f x
return y
De-sugared into using the (>>=) operator:
(>>|) xs f = xs >>= \x ->
f x >>= \y ->
return y
This can be shortened (one rewrite per line):
(>>|) xs f = xs >>= \x -> f x >>= \y -> return y -- eta-reduction
≡ (>>|) xs f = xs >>= \x -> f x >>= return -- monad identity
≡ (>>|) xs f = xs >>= \x -> f x -- eta-reduction
≡ (>>|) xs f = xs >>= f -- prefix operator
≡ (>>|) xs f = (>>=) xs f -- point-free
≡ (>>|) = (>>=)
So from using list comprehensions, you haven't really declared a new definition, you're just relying on the existing one. If you wanted, you could instead define your instance Monadd [] without relying on existing Monad instances or list comprehensions:
Using concatMap:
instance Monadd [] where
(>>|) xs f = concatMap f xs
Spelling that out a little more:
instance Monadd [] where
(>>|) xs f = concat (map f xs)
Spelling that out even more:
instance Monadd [] where
(>>|) [] f = []
(>>|) (x:xs) f = let ys = f x in ys ++ ((>>|) xs f)
The Monadd type class should have something similar to return. I'm not sure why it's missing.
Monads are often easier understood with the “mathematical definition”, than with the methods of the Haskell standard class. Namely,
class Applicative' m => Monadd m where
join :: m (m a) -> m a
Note that you can implement the standard version in terms of this, vice versa:
join mma = mma >>= id
ma >>= f = join (fmap f ma)
For lists, join (aka concat) is particularly simple:
join :: [[a]] -> [a]
join xss = [x | xs <- xss, x <- xs] -- xss::[[a]], xs::[a]
-- join [[1],[2]] ≡ [1,2]
For the example you find confusing, you'd have
[1,2,3,4] >>= \x->[(x+1)]
≡ join $ fmap (\x->[(x+1)]) [1,2,3,4]
≡ join [[1+1], [2+1], [3+1], [4+1]]
≡ join [[2],[3],[4],[5]]
≡ [2,3,4,5]
List comprehensions are just like nested loops:
xs >>| foo = [ y | x <- xs, y <- foo x]
-- = for x in xs:
-- for y in (foo x):
-- yield y
Thus we have
[1,2,3,4] >>| (\x -> [x, x+10])
=
[ y | x <- [1,2,3,4], y <- (\x -> [x, x+10]) x]
=
[ y | x <- [1] ++ [2,3,4], y <- [x, x+10]]
=
[ y | x <- [1], y <- [x, x+10]] ++ [ y | x <- [2,3,4], y <- [x, x+10]] -- (*)
=
[ y | y <- [1, 1+10]] ++ [ y | x <- [2,3,4], y <- [x, x+10]]
=
[ y | y <- [1]] ++ [ y | y <- [11]] ++ [ y | x <- [2,3,4], y <- [x, x+10]]
=
[1] ++ [11] ++ [ y | x <- [2,3,4], y <- [x, x+10]]
=
[1, 11] ++ [2, 12] ++ [ y | x <- [3,4], y <- [x, x+10]]
=
[1, 11] ++ [2, 12] ++ [3, 13] ++ [ y | x <- [4], y <- [x, x+10]]
=
[1, 11] ++ [2, 12] ++ [3, 13] ++ [4, 14]
The crucial step is marked (*). You can take it as the definition of what list comprehensions are.
A special case is when the foo function returns a singleton list, like in your question. Then it is indeed tantamount to mapping, as each element in the input list is turned into one (transformed) element in the output list.
But list comprehensions are more powerful. An input element can also be turned conditionally into no elements (working as a filter), or several elements:
[ a, [a1, a2] ++ concat [ [a1, a2], [ a1, a2,
b, ==> [b1] ++ == [b1], == b1,
c, [] ++ [],
d ] [d1, d2] [d1, d2] ] d1, d2 ]
The above is equivalent to
concat (map foo [a,b,c,d])
=
foo a ++ foo b ++ foo c ++ foo d
for some appropriate foo.
concat is list monad's join, and map is list monad's fmap. In general, for any monad,
m >>= foo = join (fmap foo m)
The essence of Monad is: from each entity "in" a "structure", conditionally producing new elements in the same kind of structure, and splicing them in-place:
[ a , b , c , d ]
/ \ | | / \
[ [a1, a2] , [b1] , [] , [d1, d2] ] -- fmap foo = [foo x | x <- xs]
-- = [y | x <- xs, y <- [foo x]]
[ a1, a2 , b1 , d1, d2 ] -- join (fmap foo) = [y | x <- xs, y <- foo x ]
I wrote a filter function:
f :: (a -> Bool) -> [a] -> [a]
f p xs = case xs of
[] -> []
x : xs' -> if p x
then x : f p xs'
else f p xs'
To understand bind, I want to implement this using bind.
What I was thinking about:
f p xs = xs >>= (\x xs -> if p x then x : f p xs else f p xs)
But I get this error:
* Couldn't match expected type `[a]' with actual type `[a] -> [a]'
* The lambda expression `\ x xs -> ...' has two arguments,
but its type `a -> [a]' has only one
In the second argument of `(>>=)', namely
`(\ x xs -> if p x then x : f p xs else f p xs)'
In the expression:
xs >>= (\ x xs -> if p x then x : f p xs else f p xs)
* Relevant bindings include
xs :: [a] (bound at <interactive>:104:5)
p :: a -> Bool (bound at <interactive>:104:3)
f :: (a -> Bool) -> [a] -> [a] (bound at <interactive>:104:1)
Successfully did it using foldr:
f p xs = foldr (\x xs -> if p x then x : f p xs else f p xs) [] xs
What's going wrong?
To understand bind, i want to implement this as bind.
There is no bind here. The bind is added in case of a do expression. The above is not a do-expression, so there is no bind here.
You can however write this with bind, like:
f p xs = xs >>= \x -> if p x then [x] else []
but this is not a literal mapping of the original function, we simply make use of the instance Monad [] implementation here. Nevertheless, your f is just filter :: (a -> Bool) -> [a] -> [a] here.
To understand bind, first implement the no-op:
id_list xs = concat [ [x] | x <- xs ] = [ y | x <- xs, y <- [x ] ]
Now for the filter, augment it as
filter p xs = concat [ [x | p x] | x <- xs ] = [ y | x <- xs, y <- [x | p x] ]
How is this code using bind, you ask? If we're using MonadComprehensions, it does.
The explicit do-notation re-write is straightforward:
id_list xs = do { x <- xs ; y <- [ x ] ; return y }
filter p xs = do { x <- xs ; y <- [ x | p x] ; return y }
And of course, for lists,
[x] == return x
[x | p x] == if p x then return x else mzero
mzero == []
concat == join
This brings us back to an explicitly recursive way to code filter as
filter p [] = []
filter p (x:xs) = [x | p x] ++ filter p xs
With bind, we think in terms of transforming each element of the list individually, into the list of results (none, one, or several) for that one input element. Your foldr-based code breaks this.
So, the code itself is just
filter_bind p xs = xs >>= (\x -> [x | p x])
because we have
xs >>= f == join (fmap f xs)
== concat (map f xs)
== concat [ f x | x <- xs ]
== foldr (++) []
[ f x | x <- xs ]
with the last snippet corresponding to the explicitly recursive definition above.
See also
How does the List monad work in this example?
Haskell Monad - How does Monad on list work?
etc.
In order to understand Monad, I came up with the following definitions:
class Applicative' f where
purea :: a -> f a
app :: f (a->b) -> f a -> f b
class Applicative' m => Monadd m where
(>>|) :: m a -> (a -> m b) -> m b
instance Applicative' [] where
purea x = [x]
app gs xs = [g x | g <- gs, x <- xs]
instance Monadd [] where
(>>|) xs f = [ y | x <-xs, y <- f x]
It works as expected:
(>>|) [1,2,3,4] (\x->[(x+1)])
[2,3,4,5]
I am not sure how it is working though.
For example:
[ y | y <- [[1],[2]]]
[[1],[2]]
How does application (\x->([x+1]) to each list element of [1,2,3] result in [2,3,4] and not [[2],[3],[4]]
Or quite simply my confusion seems to stem from not understanding how this statement [ y | x <-xs, y <- f x] actually works
Wadler, School of Haskell, LYAH, HaskellWiki, Quora and many more describe the list monad.
Compare:
(=<<) :: Monad m => (a -> m b) -> m a -> m b for lists with
concatMap :: (a -> [b]) -> [a] -> [b] for m = [].
The regular (>>=) bind operator has the arguments flipped, but is otherwise just an infix concatMap.
Or quite simply my confusion seems to stem from not understanding how this statement actually works:
(>>|) xs f = [ y | x <- xs, y <- f x ]
Since list comprehensions are equivalent to the Monad instance for lists, this definition is kind of cheating. You're basically saying that something is a Monadd in the way that it's a Monad, so you're left with two problems: Understanding list comprehensions, and still understanding Monad.
List comprehensions can be de-sugared for a better understanding:
Removing syntactic sugar: List comprehension in Haskell
In your case, the statement could be written in a number of other ways:
Using do-notation:
(>>|) xs f = do x <- xs
y <- f x
return y
De-sugared into using the (>>=) operator:
(>>|) xs f = xs >>= \x ->
f x >>= \y ->
return y
This can be shortened (one rewrite per line):
(>>|) xs f = xs >>= \x -> f x >>= \y -> return y -- eta-reduction
≡ (>>|) xs f = xs >>= \x -> f x >>= return -- monad identity
≡ (>>|) xs f = xs >>= \x -> f x -- eta-reduction
≡ (>>|) xs f = xs >>= f -- prefix operator
≡ (>>|) xs f = (>>=) xs f -- point-free
≡ (>>|) = (>>=)
So from using list comprehensions, you haven't really declared a new definition, you're just relying on the existing one. If you wanted, you could instead define your instance Monadd [] without relying on existing Monad instances or list comprehensions:
Using concatMap:
instance Monadd [] where
(>>|) xs f = concatMap f xs
Spelling that out a little more:
instance Monadd [] where
(>>|) xs f = concat (map f xs)
Spelling that out even more:
instance Monadd [] where
(>>|) [] f = []
(>>|) (x:xs) f = let ys = f x in ys ++ ((>>|) xs f)
The Monadd type class should have something similar to return. I'm not sure why it's missing.
Monads are often easier understood with the “mathematical definition”, than with the methods of the Haskell standard class. Namely,
class Applicative' m => Monadd m where
join :: m (m a) -> m a
Note that you can implement the standard version in terms of this, vice versa:
join mma = mma >>= id
ma >>= f = join (fmap f ma)
For lists, join (aka concat) is particularly simple:
join :: [[a]] -> [a]
join xss = [x | xs <- xss, x <- xs] -- xss::[[a]], xs::[a]
-- join [[1],[2]] ≡ [1,2]
For the example you find confusing, you'd have
[1,2,3,4] >>= \x->[(x+1)]
≡ join $ fmap (\x->[(x+1)]) [1,2,3,4]
≡ join [[1+1], [2+1], [3+1], [4+1]]
≡ join [[2],[3],[4],[5]]
≡ [2,3,4,5]
List comprehensions are just like nested loops:
xs >>| foo = [ y | x <- xs, y <- foo x]
-- = for x in xs:
-- for y in (foo x):
-- yield y
Thus we have
[1,2,3,4] >>| (\x -> [x, x+10])
=
[ y | x <- [1,2,3,4], y <- (\x -> [x, x+10]) x]
=
[ y | x <- [1] ++ [2,3,4], y <- [x, x+10]]
=
[ y | x <- [1], y <- [x, x+10]] ++ [ y | x <- [2,3,4], y <- [x, x+10]] -- (*)
=
[ y | y <- [1, 1+10]] ++ [ y | x <- [2,3,4], y <- [x, x+10]]
=
[ y | y <- [1]] ++ [ y | y <- [11]] ++ [ y | x <- [2,3,4], y <- [x, x+10]]
=
[1] ++ [11] ++ [ y | x <- [2,3,4], y <- [x, x+10]]
=
[1, 11] ++ [2, 12] ++ [ y | x <- [3,4], y <- [x, x+10]]
=
[1, 11] ++ [2, 12] ++ [3, 13] ++ [ y | x <- [4], y <- [x, x+10]]
=
[1, 11] ++ [2, 12] ++ [3, 13] ++ [4, 14]
The crucial step is marked (*). You can take it as the definition of what list comprehensions are.
A special case is when the foo function returns a singleton list, like in your question. Then it is indeed tantamount to mapping, as each element in the input list is turned into one (transformed) element in the output list.
But list comprehensions are more powerful. An input element can also be turned conditionally into no elements (working as a filter), or several elements:
[ a, [a1, a2] ++ concat [ [a1, a2], [ a1, a2,
b, ==> [b1] ++ == [b1], == b1,
c, [] ++ [],
d ] [d1, d2] [d1, d2] ] d1, d2 ]
The above is equivalent to
concat (map foo [a,b,c,d])
=
foo a ++ foo b ++ foo c ++ foo d
for some appropriate foo.
concat is list monad's join, and map is list monad's fmap. In general, for any monad,
m >>= foo = join (fmap foo m)
The essence of Monad is: from each entity "in" a "structure", conditionally producing new elements in the same kind of structure, and splicing them in-place:
[ a , b , c , d ]
/ \ | | / \
[ [a1, a2] , [b1] , [] , [d1, d2] ] -- fmap foo = [foo x | x <- xs]
-- = [y | x <- xs, y <- [foo x]]
[ a1, a2 , b1 , d1, d2 ] -- join (fmap foo) = [y | x <- xs, y <- foo x ]
I have the following function
combinations :: [[a]] -> [[a]]
combinations [] = [[]]
combinations (xs:xss) = concat [map (x:) yss | x <- xs]
where yss = combinations xss
Which produces all combinations between its elements:
*Main> combinations [[1,2],[2,3,4],[5,6]]
[[1,2,5],[1,2,6],[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,2,5],[2,2,6],[2,3,5],[2,3,6]
,[2,4,5],[2,4,6]]
I some how feel there must be a monadic way to do this
foobar = do
n <- [1,2]
ch <- [3,4,5]
return[n,ch]
This is how far I came. But I am stuck.
Your function is sequence for the list monad.
> :t sequence
sequence :: Monad m => [m a] -> m [a]
> sequence [[1,2],[2,3,4],[5,6]]
[[1,2,5],[1,2,6],[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,2,5],[2,2,6],[2,3,5],[2,3,6],
[2,4,5],[2,4,6]]
The best I've been able to come up with is
combinations [] = [[]]
combinations (xs:xss) = do
x <- xs
ys <- combinations xss
return $ x : ys
The way I derived this was I first converted the list comprehension into monadic code (which also meant dropping the concat to get it to type check)
combinations (xs:xss) =
let yss = combinations xss
in do
x <- xs
map (x:) yss
Then I realized that map (x:) yss is exactly fmap (x:) yss, which is exactly yss >>= return . (x:), so I knew I could do
combinations (xs:xss) =
let yss = combinations xss
in do
x <- xs
ys <- yss
return $ x : ys
And then it can be inlined as
combinations (xs:xss) = do
x <- xs
ys <- combinations xss
return $ x : ys
I have a function for finite lists
> kart :: [a] -> [b] -> [(a,b)]
> kart xs ys = [(x,y) | x <- xs, y <- ys]
but how to implement it for infinite lists? I have heard something about Cantor and set theory.
I also found a function like
> genFromPair (e1, e2) = [x*e1 + y*e2 | x <- [0..], y <- [0..]]
But I'm not sure if it helps, because Hugs only gives out pairs without ever stopping.
Thanks for help.
Your first definition, kart xs ys = [(x,y) | x <- xs, y <- ys], is equivalent to
kart xs ys = xs >>= (\x ->
ys >>= (\y -> [(x,y)]))
where
(x:xs) >>= g = g x ++ (xs >>= g)
(x:xs) ++ ys = x : (xs ++ ys)
are sequential operations. Redefine them as alternating operations,
(x:xs) >>/ g = g x +/ (xs >>/ g)
(x:xs) +/ ys = x : (ys +/ xs)
[] +/ ys = ys
and your definition should be good to go for infinite lists as well:
kart_i xs ys = xs >>/ (\x ->
ys >>/ (\y -> [(x,y)]))
testing,
Prelude> take 20 $ kart_i [1..] [101..]
[(1,101),(2,101),(1,102),(3,101),(1,103),(2,102),(1,104),(4,101),(1,105),(2,103)
,(1,106),(3,102),(1,107),(2,104),(1,108),(5,101),(1,109),(2,105),(1,110),(3,103)]
courtesy of "The Reasoned Schemer". (see also conda, condi, conde, condu).
another way, more explicit, is to create separate sub-streams and combine them:
kart_i2 xs ys = foldr g [] [map (x,) ys | x <- xs]
where
g a b = head a : head b : g (tail a) (tail b)
this actually produces exactly the same results. But now we have more control over how we combine the sub-streams. We can be more diagonal:
kart_i3 xs ys = g [] [map (x,) ys | x <- xs]
where -- works both for finite
g [] [] = [] -- and infinite lists
g a b = concatMap (take 1) a
++ g (filter (not . null) (take 1 b ++ map (drop 1) a))
(drop 1 b)
so that now we get
Prelude> take 20 $ kart_i3 [1..] [101..]
[(1,101),(2,101),(1,102),(3,101),(2,102),(1,103),(4,101),(3,102),(2,103),(1,104)
,(5,101),(4,102),(3,103),(2,104),(1,105),(6,101),(5,102),(4,103),(3,104),(2,105)]
With some searching on SO I've also found an answer by Norman Ramsey with seemingly yet another way to generate the sequence, splitting these sub-streams into four areas - top-left tip, top row, left column, and recursively the rest. His merge there is the same as our +/ here.
Your second definition,
genFromPair (e1, e2) = [x*e1 + y*e2 | x <- [0..], y <- [0..]]
is equivalent to just
genFromPair (e1, e2) = [0*e1 + y*e2 | y <- [0..]]
Because the list [0..] is infinite there's no chance for any other value of x to come into play. This is the problem that the above definitions all try to avoid.
Prelude> let kart = (\xs ys -> [(x,y) | ls <- map (\x -> map (\y -> (x,y)) ys) xs, (x,y) <- ls])
Prelude> :t kart
kart :: [t] -> [t1] -> [(t, t1)]
Prelude> take 10 $ kart [0..] [1..]
[(0,1),(0,2),(0,3),(0,4),(0,5),(0,6),(0,7),(0,8),(0,9),(0,10)]
Prelude> take 10 $ kart [0..] [5..10]
[(0,5),(0,6),(0,7),(0,8),(0,9),(0,10),(1,5),(1,6),(1,7),(1,8)]
you can think of the sequel as
0: (0, 0)
/ \
1: (1,0) (0,1)
/ \ / \
2: (2,0) (1, 1) (0,2)
...
Each level can be expressed by level n: [(n,0), (n-1, 1), (n-2, 2), ..., (0, n)]
Doing this to n <- [0..]
We have
cartesianProducts = [(n-m, m) | n<-[0..], m<-[0..n]]