I'd like to take from these two lists to create a list of all combinations, where each combination is also a list.
E.g.
Given two lists: [1,2,3] and [True, False]
Combinations:
[(1, False), (2, False), (3, False)]
[(1, False), (2, False), (3, True )]
[(1, False), (2, True ), (3, False)]
[(1, True ), (2, False), (3, False)]
[(1, False), (2, True ), (3, True )]
[(1, True ), (2, False), (3, True )]
[(1, True ), (2, True ), (3, False)]
[(1, True ), (2, True ), (3, True )]
There should be 2^n combinations where n is the number of numbers.
EDIT:
Tried to do the following:
[(n, b) | n <- [1,2,3], b <- [True, False]]
(,) <$> [1,2,3] <*> [True, False]
We can avoid using length, which might be unsafe, since the list can have infinite length. By using recursion or a foldr pattern, we avoid that:
{-# LANGUAGE TupleSections #-}
allComb :: [b] -> [a] -> [[(a,b)]]
allComb vs = go
where go [] = [[]]
go (x:xs) = (:) <$> map (x,) vs <*> go xs
or with a foldr-pattern in a one-liner:
allComb :: [b] -> [a] -> [[(a,b)]]
allComb vs = foldr (\x -> ((:) <$> map (x,) vs <*>)) [[]]
For example:
Prelude> allComb [False, True] [1,2,3]
[[(1,False),(2,False),(3,False)],[(1,False),(2,False),(3,True)],[(1,False),(2,True),(3,False)],[(1,False),(2,True),(3,True)],[(1,True),(2,False),(3,False)],[(1,True),(2,False),(3,True)],[(1,True),(2,True),(3,False)],[(1,True),(2,True),(3,True)]]
The above approach will not work on infinite lists, although we can, given the first list contains at least one element, slightly alter the code, to generate the first element of the result: a list that zips all the elements in the second list with that item. I leave that as an exercise.
This can't be the most straightforward or most efficient answer.
But using the technique from How to generate a list of all possible strings from shortest to longest we can generate a list of all possible Boolean sequences. We take the ones that are the same length as the second list and then zip them with that list.
allBoolPermutations :: Int -> [[Bool]]
allBoolPermutations n = takeWhile (\l -> length l == n)
$ dropWhile (\l -> length l < n)
$ allBools
where
allBools = [ c : s | s <- []:allBools, c <- [True, False]]
zipWithBoolPermutations :: [a] -> [[(a, Bool)]]
zipWithBoolPermutations someList = map (zip someList)
(allBoolPermutations (length someList))
Then zipWithBoolPermutations [1,2,3] should give you what you want.
Your desired output can be produced by defining
foo :: [a] -> [b] -> [[(a, b)]]
foo nums bools =
map (zip nums) . sequence $ replicate (length nums) bools
=
let n = length nums
in
[ zip nums bs | bs <- sequence $ replicate n bools]
and calling
foo [1,2,3] [False, True]
That call is equivalent to
let nums = [1,2,3]
bools = [False, True]
n = 3
in
[ zip nums bs | bs <- sequence $ replicate n bools]
=
[ zip [1,2,3] bs | bs <- sequence $ replicate 3 [False, True]]
=
[ zip [1,2,3] (b:bs) | b <- [False, True]
, bs <- sequence $ replicate 2 [False, True]]
=
[ zip [1,2,3] (b:c:bs) | b <- [False, True]
, c <- [False, True]
, bs <- sequence $ replicate 1 [False, True]]
=
[ zip [1,2,3] (b:c:d:bs) | b <- [False, True]
, c <- [False, True]
, d <- [False, True]
, bs <- sequence $ replicate 0 [False, True] ]
=
[ zip [1,2,3] (b:c:d:bs) | b <- [False, True]
, c <- [False, True]
, d <- [False, True]
, bs <- sequence [] ]
=
[ zip [1,2,3] (b:c:d:bs) | b <- [False, True]
, c <- [False, True]
, d <- [False, True]
, bs <- [[]] ]
=
[ zip [1,2,3] (b:c:d:[]) | b <- [False, True]
, c <- [False, True]
, d <- [False, True] ]
i.e.
[ zip [1,2,3] [b,c,d] | b <- [False, True]
, c <- [False, True]
, d <- [False, True] ]
and if evaluate this last expression, we also get the same result.
Filling up the three spaces with each possible combination of the two available values is like having all possible functions from 3 spaces to 2 values, whatever those spaces and values are.
Mathematicians write this function as 23, and indeed, we get 2^3 = 8 outputs.
edit: the sequence ... replicate combo is actually just reimplementing another built-in, replicateM:
foo ns bs = map (zip ns) (replicateM (length ns) bs)
because replicateM n a is just like sequence (replicate n a), but without actually building the intermediate list.
For the pointfree aficionados, we can thus have
foo ns = map (zip ns) . replicateM (length ns)
= (.) ((map . zip) ns) ((replicateM . length) ns)
= ((.) . map . zip <*> replicateM . length) ns
i.e.
foo = (.) . map . zip <*> replicateM . length
Nice and short:
traverse ((<$> [True, False]) . (,)) [1,2,3]
Or less pointfree, but perhaps more understandable:
traverse (\x -> [(x,True), (x,False)]) [1,2,3]
The inner function ((<$> [True, False]) . (,) or \x -> [(x,True), (x,False)]) takes each element such as 1 and turns it into [(1,True),(1,False)]. If you think of traverse f as being sequence . fmap f, then the fmap f part means do that function to each thing in the list (yielding [[(1,True),(1,False)],[(2,True),(2,False)],[(3,True),(3,False)]]), and the sequence part means combine them with the List applicative (which models non-determinism) to create all possible combinations (yielding [[(1,True),(2,True),(3,True)],[(1,True),(2,True),(3,False)],[(1,True),(2,False),(3,True)],[(1,True),(2,False),(3,False)],[(1,False),(2,True),(3,True)],[(1,False),(2,True),(3,False)],[(1,False),(2,False),(3,True)],[(1,False),(2,False),(3,False)]]).
Related
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.
Let's say I have the following input:
[(0, [1, 2]) , (2, [3, 4]) , (4, [])
This is an adjacency list and I want to convert it as such:
[(0,1), (0,2), (2,3), (2, 4)] -- notice how there is no 4 mapping to anything
Here is what I have so far:
conv :: [(Int, [Int])] -> [(Int, Int)]
conv adj = map fn adj -- mapping (0, [1, 2]) should give me [(0, 1), (0, 2)]
fn:: (Int, [Int]) -> [(Int, Int)]
fn (rt, list) = -- somehow perform [(rt, l[0]), (rt, l[1]) ...]
List comprehension can do the trick:
conv :: [(a, [b])] -> [(a, b)]
conv xys = [(x, y) | (x, ys) <- xys, y <- ys ]
Or we can use concatMap here:
conv :: Foldable f => f (a, [b]) -> [(a, b)]
conv = concatMap (uncurry (map . (,)))
Here the inner function uncurry (map . (,)) takes a tuple (x, ys) and thus performs a map (x,): the uncurry basically unpacks the tuple (x, ys), and calls (map . (,)) x ys, so that means that we obtain (map (x,)) ys. The above syntax uses the TupleSections extension, but we do not need to activate that extension in the real program, since we never write such syntax. Your fn function you defined is thus equivalent to uncurry (map . (,)).
We thus use this function in a concatMap that will pass the 2-tuples, and concatenate the lists these individual tuples create.
or we can use the "bind" >>= :: Monad m => m a -> (a -> m b) -> m b function:
conv :: Monad m => m (a, m b) -> m (a, b)
conv = (=<<) (\(x, ys) -> ys >>= return . (x,))
or shorter:
conv :: Monad m => m (a, m b) -> m (a, b)
conv = (=<<) (uncurry (fmap . (,)))
the nice thing about the latter is that it also works with Maybes, etc. For example:
Prelude> conv [(0, [1, 2]) , (2, [3, 4]) , (4, [])]
[(0,1),(0,2),(2,3),(2,4)]
Prelude> conv Nothing
Nothing
Prelude> conv (Just (3, Nothing))
Nothing
Prelude> conv (Just (3, Just 2))
Just (3,2)
Taking advantage of instance Traversable ((,) a), we have this remarkably short (and remarkably inscrutable) solution:
conv :: [(Int, [Int])] -> [(Int, Int)]
conv = (sequence =<<)
The most general type of (sequence =<<) is (Monad m, Traversable t) => m (t (m a)) -> m (t a).
So, I am given a list containing tuples and I need to break it down into two lists, the first list containing the elements with odd index and the second list containing the elements with even index, must be done using fold, here is my attempt:
breakList :: [(Integer, Integer)] -> [[(Integer, Integer)]]
breakList [] = [[], []]
breakList xxs#(x:xs) = foldl (\ acc y -> if length (acc !! 0) < length (acc !! 1) then y : (acc !! 0) else y : (acc !! 1) ) [[], []] xxs
Error I am getting:
Couldn't match type '(Integer, Integer)'
with '[(Integer, Integer)]'
Expected type: [[(Integer, Integer)]]
when hovering over y : (acc !! 1) and y : (acc !! 0)
Example:
Input:
ex1 = [ (2, 2), (1, 3), (2, 3), (2, 4), (3, 5), (0, 2), (2, 1), (1, 4)
, (2, 0), (1, 2), (3, 1), (1, 0)]
Output
breakList ex1
== ( [(2,2),(2,3),(3,5),(2,1),(2,0),(3,1)] , [(1,3),(2,4),(0,2),(1,4),(1,2),(1,0)])
The standard trick here, as hinted at by Willem in the comments, which I first saw few years back on SO in an (F# or Ocaml) answer by [user:Ed'ka], is
evenodds :: [a] -> ([a], [a])
evenodds xs = foldr g ([],[]) xs
where
g x ~(as,bs) = (bs,x:as)
or
oddevens :: [a] -> ([a], [a])
oddevens xs = foldr g ([],[]) xs
where
g x ~(bs,as) = (x:as,bs)
What are odd positions from here, are even positions from the position one notch further on the list.
The tilde ~ introduces a lazy pattern so that the function is properly lazy in its operations.
Note that you want to split a list into two lists of a pair, so the return type should be
([(Integer, Integer)], [(Integer, Integer)])
not
[[(Integer, Integer)]]
and access the element of pair, you can use fst and snd instead of through index, and finally, use foldl will return the resulted list in reversed order, it can be fixed use foldr instead. The correction look like:
breakList :: [(Integer, Integer)]->([(Integer, Integer)], [(Integer, Integer)])
breakList xxs = foldr (\y acc-> if length (fst acc) < length (snd acc)
then (y:(fst acc), snd acc)
else (fst acc, y:(snd acc)) ) ([], []) xxs
I am trying to bend my head around list monads in haskell. I was trying to generate a list of all possible propositions given a list of strings designating boolean variables.
For instance calling :
mapM_ print $ allPropositions ["a","b"]
would yield the following result :
[("a",True),("b",True)]
[("a",True),("b",False)]
[("a",False),("b",True)]
[("a",False),("b",False)]
I have managed to do it using list comprehensions and recursion with the following code
allPropositions :: [String] -> [[(String,Bool)]]
allPropositions [] = [[]]
allPropositions (x:xs) = [(x,True):r | r <- allPropositions xs] ++ [(x,False):r | r <- allPropositions xs]
I was looking for a way to do it using the do notation similar to the following snippet but with a variable number of inputs. Is there a way to do it (nested monads,...) ?
allPropositions' = do
a <- [True, False]
b <- [True, False]
return([("a",a),("b",b)])
What you need is sequence :: Monad m => [m a] -> m [a].
In particular, for the [] monad, sequence takes a list of n lists, and produces all n-length lists drawing one element from each list at a time.
sequence [ [1,2,3], [4,5], [6] ] =
[ [1,4,6], [1,5,6], [2,4,6], [2,5,6], [3,4,6], [3,5,6] ]
This helps in your particular case because if you have a list of n strings, you can produce the possibilities for each string easily:
map (\s -> [(s,True), (s,False)] ["a", "b", "c"] =
[ [("a", True), ("a", False) ]
, [("b", True), ("b", False) ]
, [("c", True), ("c", False) ]
]
now you just need to pick one from each list to get your propositions holding a truth value for each variable:
sequence (map (\s -> [(s,True), (s,False)] ["a", "b", "c"]) =
[ [("a", True), ("b", True), ("c", True)]
, [("a", True), ("b", True), ("c", False)]
, [("a", True), ("b", False), ("c", True)]
, [("a", True), ("b", False), ("c", False)]
, [("a", False), ("b", True), ("c", True)]
, [("a", False), ("b", True), ("c", False)]
, [("a", False), ("b", False), ("c", True)]
, [("a", False), ("b", False), ("c", False)]
]
sequence (map f xs) comes up often enough that there's a name for it:
mapM f xs = sequence (map f xs)
-- or, point-free style
mapM f = sequence . map f
So your desired function is just
allPropositions vs = mapM (\v -> [(v,True),(v,False)]) vs
-- or, equivalently
allPropositions = mapM (\v -> [(v,True),(v,False)])
-- or, equivalently
allPropositions = mapM $ \v -> [(v,True),(v,False)]
-- or, equivalently, with -XTupleSections
allPropositions = mapM $ \v -> map (v,) [True, False]
This is how I would do it:
allPropositions :: [a] -> [[(a, Bool)]]
allPropositions = foldr (\x xs -> (:) <$> [(x,True),(x,False)] <*> xs) [[]]
You don't need the full power of monads at all. All you need are applicative functors.
Here's whats happening:
For the basis case the result is [[]] (i.e. allPropositions [] = [[]]).
For the inductive case the result is ⟦(:) [(x,True),(x,False)] xs⟧. Note that the double square brackets (i.e. ⟦⟧) denote the context of an applicative functor (in this case, []).
Although rampion's answer is correct, it makes use of sequence and mapM which are monadic functions. However, as I stated before you don't need the full power of monads in this case.
If you don't want the full power of monads, you can still use sequenceA.
I am a relative haskell newbie and am trying to create a list of tuples with an equation I named splits that arises from a single list originally, like this:
splits [1..4] --> [ ([1],[2,3,4]), ([1,2],[3,4]), ([1,2,3],[4]) ]
or
splits "xyz" --> [ ("x","yz"), ("xy","z") ]
Creating a list of tuples that take 1, then 2, then 3 elements, etc. I figured out I should probably use the take/drop functions, but this is what I have so far and I'm running into a lot of type declaration errors... Any ideas?
splits :: (Num a) => [a] -> [([a], [a])]
splits [] = error "shortList"
splits [x]
| length [x] <= 1 = error "shortList"
| otherwise = splits' [x] 1
where splits' [x] n = [(take n [x], drop n [x])] + splits' [x] (n+1)
The Haskell-y approach is to use the inits and tails functions from Data.List:
inits [1,2,3,4] = [ [], [1], [1,2], [1,2,3], [1,2,3,4] ]
tails [1,2,3,4] = [ [1,2,3,4], [2,3,4], [3,4], [4], [] ]
We then just zip these two lists together and drop the first pair:
splits xs = tail $ zip (inits xs) (tails xs)
or equivalently, drop the first element of each of the constituent lists first:
= zip (tail (inits xs)) (tail (tails xs))
splits [] = []
splits [_] = []
splits (x:xs) = ([x], xs) : map (\(ys, zs) -> (x:ys, zs)) (splits xs)
You have several mistakes.
You don't need to have Num a class for a.
use [] or [x] as pattern, but not a variable, use xs instead.
Use ++ instead of + for concatenating lists.
In our case use (:) to add list to value instead of ++.
Add stop for recursion, like additional variable maxn to splits'
splits :: [a] -> [([a], [a])]
splits [] = error "shortList"
splits xs
| lxs <= 1 = error "shortList"
| otherwise = splits' xs 1 lxs
where
lxs = length xs
splits' xs n maxn
| n > maxn = []
| otherwise = (take n xs, drop n xs) : splits' xs (n+1) maxn
There is a built in function that kind of does a part of what you want:
splitAt :: Int -> [a] -> ([a], [a])
which does what it looks like it would do:
> splitAt 2 [1..4]
([1,2],[3,4])
Using this function, you can just define splits like this:
splits xs = map (flip splitAt xs) [1..length xs - 1]