I was reading about list monads and encountered:
[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
it produces
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]
Here's how I understand it:
Implicit parentheses are:
([1,2] >>= \n -> ['a','b']) >>= (\ch -> return (n,ch))
([1,2] >>= \n -> ['a','b']) should give [('a',1),('b',1),('a',2),('b',2)]
because
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs) -- this line
fail _ = []
so concat (map f xs) is concat (map (\n -> ['a','b']) [1,2]) which should produce [('a',1),('b',1),('a',2),('b',2)] - quite the opposite of the actual output.
Then I don't understand >>= (\ch -> return (n,ch)) part - I think that n here has no sense. That specific reasoning is flawed, could you please explain how that expression([1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)) is computed step-by-step?
Your implicit parentheses are wrong. The way you have it, the n parameter to the first lambda would not be in scope in the return. It is more like:
([1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch))))
Which becomes:
concatMap (\n -> concatMap (\ch -> [(n,ch)]) ['a','b']) [1,2]
No, you're using wrong parenthesization. It's nested to the right, so that
[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
=
[1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch) ))
=
do { n <- [1,2]
; do { ch <- ['a','b']
; return (n,ch) }}
=
for n in [1,2]: -- pseudocode
for ch in ['a','b']:
return (n,ch)
=
[ r | n <- [1,2], ch <- ['a','b'], r <- [(n,ch)] ] -- return == (:[])
=
[ (n,ch) | n <- [1,2], ch <- ['a','b'] ]
=
pure (,) <*> [1,2] <*> ['a','b'] -- using list applicative
=
[(1,'a'), (1,'b'), (2,'a'), (2,'b')]
and the innermost list is "spinning" the fastest, like in a car's odometer.
You are absolutely right, with the wrong parenthesization the n binding would make no sense. It is precisely for that reason that it must associate to the right, to make the nested binding possible; for the nested computations are the essence of the monad:
[ foo x | x <- xs ] -- functor : amendable computations
[ bar x y | x <- xs AND y <- ys ] -- applicative : combinable computations
[ baz x y | x <- xs, y <- foo x ] -- monad : reinterpretative computations
(and yes, omitting parentheses in learning material is the root of all evil... not really, but still...)
Implicit parentheses are:
([1,2] >>= \n -> ['a','b']) >>= (\ch -> return (n,ch))
This is wrong. \ has the lowest precedence and thus extends to the end of the expression. So the parentheses are:
[1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch)))
([1,2] >>= \n -> ['a','b']) should give [('a',1),('b',1),('a',2),('b',2)]
As you can see from the above parenthesization ([1,2] >>= \n -> ['a','b']), isn't actually a subexpression of the given expression. But if it were, its result would be ['a', 'b', 'a', 'b']. n is not actually used anywhere in the expressions ['a', 'b'], so there's no way the numbers could appear in the result.
Then I don't understand >>= (\ch -> return (n,ch)) part - I think that n here has no sense.
Given your parenthesization n would indeed be undefined there. However given the proper parenthesization it should be clear where n comes from: We're still inside the \n -> ... function, so n still refers to the argument of that function, namely the current element of the [1, 2] list.
You're wrong about the semantics of concat (map (\n -> ['a','b']) [1,2]). I've done a step by step evaluation of it below.
concat (map (\n -> ['a','b']) [1,2])
concat [(\n -> ['a','b']) 1, (\n -> ['a','b']) 2]
concat [['a','b'], ['a','b']]
['a','b','a','b']
The last bind is what is used to actually make it a list of tuples.
Related
For a college assignment I am learning Haskell and when reading about the do-notation and sequencing with >>= and >> I came across this behaviour that I did not expect.
[1,2,3] >> [1] -- returns [1,1,1]
Can anyone explain why every element of the first array is replaced by the elements of the second array? It seems like the list is concatenated in some way, while I expected the result of the first expression to be completely ignored, thus I would expect [1] as the result.
Thanks a lot in advance.
The “result” is in this case the values contained in [1,2,3], which are indeed ignored. What >> does not ignore is the context, which for the list monad is the shape (i.e. length) of the list. This can't be ignored, because we must have x >>= pure ≡ x, i.e.
Prelude> [1,2,3] >>= pure
[1,2,3]
Prelude> [1,2,3] >>= \n -> [n]
[1,2,3]
Prelude> [1,2,3] >>= \n -> [1]
[1,1,1]
Prelude> [1,2,3] >>= \_ -> [1]
[1,1,1]
Prelude> [1,2,3] >> [1]
[1,1,1]
An example with length>1 on the RHS:
[1,2,3] >>= \n -> [n, n+10]
[1,11,2,12,3,13]
Prelude> [1,2,3] >>= \n -> [100, 10]
[100,10,100,10,100,10]
Prelude> [1,2,3] >> [100, 10]
[100,10,100,10,100,10]
There are several equivalent ways of writing [1,2,3] >> [1]:
do [1,2,3]
return 1
[ x | _ <- [1,2,3], x <- [1] ]
[ 1 | _ <- [1,2,3] ]
[1,2,3] >>= \_ -> [1]
concatMap (const [1]) [1,2,3]
concat (map (const [1]) [1,2,3])
concat ([1,2,3] $> [1])
It replaces every element of [1..3] with [1] and then collapses it:
concatMap (\_ -> [1]) [1,2,3]
= concat (map (\_ -> [1]) [1,2,3])
= concat [[1],[1],[1]]
= [1,1,1]
It completely ignores the elements of [1,2,3], just using the shape (length). Look what happens if we replace them with undefined:
> do [undefined, undefined, undefined]; return 1
[1,1,1]
The results of the first computation are indeed ignored.
Monads can be seen as generalized nested loops. What you have can be written in pseudocode as
for y in [1,2,3]:
for x in [1]: -- for x in ((\_ -> [1]) y):
yield x
Both y and x are in scope at the innermost level. y's value is indeed ignored.
Still for each y in [1,2,3] each x in [1] is produced, thus defining the overall computation. For lists this means the results produced one by one by the combined computation as a whole are the results produced one by one at the innermost level. Sounds trivial, isn't it.
How exactly this is implemented is an implementational detail. Seeing the lists as data this means splicing the results of the inner computations in place, flattening the list of lists into a one-level list, appending the inner lists together. concatMap is widely known as flatMap in other languages:
[ 1, 2, 3 ]
[1] [1] [1]
-------------------
[ 1, 1, 1 ]
Related answers: Why >> duplicates right-hand side operand , Map and flatMap , How does Monad on list work? , Why list monad combines in that order? , mapM with const functions in Haskell , under the hood reason we can use nested loops in list comprehensions , Generalizing prime pairs in SICP.
My Problem is that I want to create a infinite list of all combinations of a given list. So for example:
infiniteListComb [1,2] = [[],[1],[2], [1,1],[1,2],[2,1],[2,2], [1,1,1], ...].
other example:
infiniteListComb [1,2,3] = [[], [1], [2], [3], [1,1], [1,2], [1,3], [2,1],[2,2],[2,3],[3,1],[3,2],[3,3],[1,1,1], ...].
Reminds me of power sets, but with lists with same elements in it.
What I tried:
I am new in Haskell. I tried the following:
infiniteListComb: [x] -> [[x]]
infiniteListComb [] = []
infiniteListComb [(x:xs), ys] = x : infiniteListComb [xs,ys]
But that did not work because it only sumed up my list again. Has anyone another idea?
Others already provided a few basic solutions. I'll add one exploiting the Omega monad.
The Omega monad automatically handles all the interleaving among infinitely many choices. That is, it makes it so that infiniteListComb "ab" does not return ["", "a", "aa", "aaa", ...] without ever using b. Roughly, each choice is scheduled in a fair way.
import Control.Applicative
import Control.Monad.Omega
infiniteListComb :: [a] -> [[a]]
infiniteListComb xs = runOmega go
where
go = -- a combination is
pure [] -- either empty
<|> -- or
(:) <$> -- a non empty list whose head is
each xs -- an element of xs
<*> -- and whose tail is
go -- a combination
Test:
> take 10 $ infiniteListComb [1,2]
[[],[1],[1,1],[2],[1,1,1],[2,1],[1,2],[2,1,1],[1,1,1,1],[2,2]]
The main downside of Omega is that we have no real control about the order in which we get the answers. We only know that all the possible combinations are there.
We iteratively add the input list xs to a list, starting with the empty list, to get the ever growing lists of repeated xs lists, and we put each such list of 0, 1, 2, ... xs lists through sequence, concatting the resulting lists:
infiniteListComb :: [a] -> [[a]]
infiniteListComb xs = sequence =<< iterate (xs :) []
-- = concatMap sequence (iterate (xs :) [])
e.g.
> take 4 (iterate ([1,2,3] :) [])
[[],[[1,2,3]],[[1,2,3],[1,2,3]],[[1,2,3],[1,2,3],[1,2,3]]]
> sequence [[1,2,3],[1,2,3]]
[[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3]]
> take 14 $ sequence =<< iterate ([1,2,3] :) []
[[],[1],[2],[3],[1,1],[1,2],[1,3],[2,1],[2,2],[2,3],[3,1],[3,2],[3,3],[1,1,1]]
The essence of Monad is flatMap (splicing map).
sequence is the real magician here. It is equivalent to
sequence [xs, ys, ..., zs] =
[ [x,y,...,z] | x <- xs, y <- ys, ..., z <- zs ]
or in our case
sequence [xs, xs, ..., xs] =
[ [x,y,...,z] | x <- xs, y <- xs, ..., z <- xs ]
Coincidentally, sequence . replicate n is also known as replicateM n. But we spare the repeated counting from 0 to the growing n, growing them by 1 at a time instead.
We can inline and fuse together all the definitions used here, including
concat [a,b,c...] = a ++ concat [b,c...]
to arrive at a recursive solution.
Another approach, drawing on answer by chi,
combs xs = ys where
ys = [[]] ++ weave [ map (x:) ys | x <- xs ]
weave ((x:xs):r) = x : weave (r ++ [xs])
There are many ways to implement weave.
Since list Applicative/Monad works via a cartesian-product like system, there's a short solution with replicateM:
import Control.Monad
infiniteListComb :: [x] -> [[x]]
infiniteListComb l = [0..] >>= \n -> replicateM n l
So what I have so far is something like this:
combs :: [[Char]]
combs = [[i] ++ [j] ++ [k] ++ [l] | i <- x, j <- x, k <- x, l <- x]
where x = "abc"
So this is the working function for n = 4, is there any way to make this work for an arbitrary number of generators? I could program in for n = 1, 2, 3 etc.. but ideally need it to work for any given n. For reference, x is just an arbitrary string of unique characters. I'm struggling to think of a way to somehow extract it to work for n generators.
You can use replicateM:
replicateM :: Applicative m => Int -> m a -> m [a]
E.g.:
generate :: Num a => Int -> [[a]]
generate = flip replicateM [1,2,3]
to generate all possiible lists of a given length and consisting of elements 1..3.
As far as I know, you can not construct list comprehension with an arbitrary number of generators, but usually if you do something with arbitrary depth, recursion is the way to do it.
So we have to think of solving this, in terms of itself. If you want all possible strings that can be generated with the characters in x. In case n = 0, we can generate exactly one string: the empty string.
combs 0 = [""]
so a list with one element [].
Now in case we want to generate strings with one characters, we can of course simply return x:
combs 1 = x
and now the question is what to do in case n > 1. In that case we can obtain all the strings with length n-1, and and for each such string, and each such character in x, produce a new string. Like:
combs n = [ (c:cs) | c <- x, cs <- combs (n-1) ]
Note that this makes the second case (n = 1) redundant. We can pick a character c from x, and prepend that to the empty string. So a basic implementation is:
combs :: Int -> [[Char]]
combs 0 = [""]
combs n = [(c:cs) | c <- x, cs <- combs (n-1)]
where x = "abc"
Now we can still look for improvements. List comprehensions are basically syntactical sugar for the list monad. So we can use liftA2 here:
import Control.Applicative(liftA2)
combs :: Int -> [[Char]]
combs 0 = [""]
combs n = liftA2 (:) x (combs (n-1))
where x = "abc"
we probably also want to make the set of characters a parameter:
import Control.Applicative(liftA2)
combs :: [Char] -> Int -> [[Char]]
combs _ 0 = [""]
combs x n = liftA2 (:) x (combs (n-1))
and we do not have to restrict us to characters, we can produce a certesian power for all possible types:
import Control.Applicative(liftA2)
combs :: [a] -> Int -> [[a]]
combs _ 0 = [[]]
combs x n = liftA2 (:) x (combs (n-1))
First I would translate the comprehension as a monadic expression.
x >>= \i -> x >>= \j -> x >>= \k -> x >>= \l -> return [i,j,k,l]
With n = 4 we see we have 4 x's, and generally will have n x's. Therefore, I am thinking about a list of x's of length n.
[x,x,x,x] :: [[a]]
How might we go from [x,x,x,x] to the monadic expression? A first good guess is foldr, since we want to do something with each element of the list. Particularly, we want to take an element from each x and form a list with these elements.
foldr :: (a -> b -> b) -> b -> [a] -> b
-- Or more accurately for our scenario:
foldr :: ([a] -> [[a]] -> [[a]]) -> [[a]] -> [[a]] -> [[a]]
There are two terms to come up with for foldr, which I will call f :: [a] -> [[a]] -> [[a]] and z :: [[a]]. We know what foldr f z [x,x,x,x] is:
foldr f z [x,x,x,x] = f x (f x (f x (f x z)))
If we add parentheses to the earlier monadic expression, we have this:
x >>= \i -> (x >>= \j -> (x >>= \k -> (x >>= \l -> return [i,j,k,l])))
You can see how the two expressions are looking similar. We should be able to find an f and z to make them the same. If we choose f = \x a -> x >>= \x' -> a >>= \a' -> return (x' : a') we get:
f x (f x (f x (f x z)))
= (\x a -> a >>= \a' -> x >>= \x' -> return (x' : a')) x (f x (f x (f x z)))
= f x (f x (f x z)) >>= \a' -> x >>= \x' -> return (x' : a')
= f x (f x (f x z)) >>= \a' -> x >>= \l -> return (l : a')
= (f x (f x z) >>= \a' -> x >>= \k -> return (k : a')) >>= \a' -> x >>= \l -> return (l : a')
= f x (f x z) >>= \a' -> x >>= \k -> x >>= \l -> return (l : k : a')
Note that I have reversed the order of i,j,k,l to l,k,j,i but in context of finding combinations, this should be irrelevant. We could try a' ++ [x'] instead if it was really of concern.
The last step is because (a >>= \b -> c) >>= \d -> e is the same as a >>= \b -> c >>= \d -> e (when accounting for variable hygiene) and return a >>= \b -> c is the same as (\b -> c) a.
If we keep unfolding this expression, eventually we will reach z >>= \a' -> … on the front. The only choice that makes sense here then is z = [[]]. This means that foldr f z [] = [[]] which may not be desirable (preferring [] instead). Instead, we might use foldr1 (for non-empty lists, and we might use Data.NonEmpty) or we might add a separate clause for empty lists to combs.
Looking at f = \x a -> x >>= \x' -> a >>= \a' -> return (x' : a') we might realise this helpful equivalence: a >>= \b -> return (c b) = c <$> a. Therefore, f = \x a -> x >>= \x' -> (x' :) <$> a. Then also, a >>= \b -> c (g b) = g <$> a >>= \b -> c and so f = (:) <$> x >>= \x' -> x' <$> a. Finally, a <*> b = a >>= \x -> x <$> b and so f = (:) <$> x <*> a.
The official implementation of sequenceA for lists is foldr (\x a -> (:) <$> x <*> a) (pure []), exactly what we came up with here too. This can be further shortened as foldr (liftA2 (:)) (pure []) but there is possibly some optimisation difference that made the implementors not choose this.
Last step is to merely come up with a list of n x's. This is just replicate replicate n x. There happens to be a function which does both replication and sequencing, called replicateM replicateM n x.
I was recently reading learn you a haskell and I came across the expression:
[1,2] >>= \n -> ['a', 'b'] >>= \ch -> return (n, ch)
This expressions returns the result
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]
so i understand that the monadic bind for lists is implemented as follows
xs >>= f = concatMap f xs
Taking the first half of the expression namely the:
[1,2] >>= \n -> ['a', 'b']
it evaluates to ['a','b','a','b'], from what I understand this is then fed in to the function: (\ch -> return (n , ch)).
What I don't understand is how the values 1,2 from the list are assigned to n and then how the compiler keeps a record of it to then assign it to n in the last function?
The first half is not what you think, the parentheses are like this :
[1,2] >>= ( \n -> ['a', 'b'] >>= ( \ch -> return (n, ch) ) )
Hi I am a newbie in Haskell.
I am trying to do a simple task.
test :: (RealFloat a) => a -> a -> [a]
test xs ys= [ w : h: [] | w <- xs, h <- ys]
I am getting an error here. (with out a doubt)
In this task, I am simply trying to bind two lists (ex: test [12.12] [14.14])
and hopefully return a new combined list (ex: [12.12,14.14])
thanks for your help
Your signature is wrong. Try:
test xs ys = ...
then in ghci:
> :t test
test :: [t] -> [t] -> [[t]]
You need two arguments, both are lists, not two arguments of single elements.
Drakosha is correct. List concatenation already has an operator in Haskell.
test :: (RealFloat a) => [a] -> [a] -> [a]
test xs ys= xs ++ ys
You probably don't want to use a list comprehension here, unless you want to extract every element in your first and second list and do something with them. For example, a Cartesian Product:
list1 = [1.0,1.1,1.2] :: [Double]
list2 = [2.0,2.1,2.2] :: [Double]
testComps xs ys = [(x,y) | x <- xs, y <- ys]
Or addition:
testComps2 xs ys = [ x + y | x <- xs, y <- ys]
Or even creating lists:
testComps3 xs ys = [x : y : [] | x <- xs, y <- ys]
In GHCi, this will yield the following:
*Main> testComps list1 list2
[(1.0,2.0),(1.0,2.1),(1.0,2.2),(1.1,2.0),(1.1,2.1),(1.1,2.2),(1.2,2.0),(1.2,2.1)
,(1.2,2.2)]
*Main> testComps2 list1 list2
[3.0,3.1,3.2,3.1,3.2,3.3000000000000003,3.2,3.3,3.4000000000000004]
*Main> testComps3 list1 list2
[[1.0,2.0],[1.0,2.1],[1.0,2.2],[1.1,2.0],[1.1,2.1],[1.1,2.2],[1.2,2.0],[1.2,2.1]
,[1.2,2.2]]
The weird results in testComps2 is, of course, normal cruft when you're dealing with floating-point numbers. In the real world you'd compensate for this by rounding.
Another problem you'll run into is the difference between (++) and (:). Simply put, (:) tacks individual items onto a list, whereas (++) concatenates two lists.
You need list concatenation:
[12.12] ++ [14.14]
=> [12.12,14.14]