Is there a function in Haskell to do the equivalent of an SQL join or an R merge ?
Basically I have two list of tuples and would like to 'zip' them according to their key.
I know there is only one or zero value for each key
a = [(1, "hello"), (2, "world")]
b = [(3, "foo"), (1, "bar")]
And get something like
[ (Just (1, "hello), Just (1, "bar))
, (Just (2, "world), Nothing)
, (Nothing , Just (3, "foo"))
]
With ordered sets (lists) and Ord key
key = fst
fullOuterJoin xs [] = map (\x -> (Just x, Nothing)) xs
fullOuterJoin [] ys = map (\y -> (Nothing, Just y)) ys
fullOuterJoin xss#(x:xs) yss#(y:ys) =
if key x == key y
then (Just x, Just y): fullOuterJoin xs ys
else
if key x < key y
then (Just x, Nothing): fullOuterJoin xs yss
else (Nothing, Just y): fullOuterJoin xss ys
(complexity is O(n+m) but if you must to sort then is O(n log n + m log m))
example
setA = [(1, "hello"), (2, "world")]
setB = [(1, "bar"), (3, "foo")]
*Main> fullOuterJoin setA setB
[(Just (1,"hello"),Just (1,"bar")),(Just (2,"world"),Nothing),(Nothing,Just (3, "foo"))]
(obviously with sort support
fullOuterJoin' xs ys = fullOuterJoin (sort xs) (sort ys)
As #Franky say, you can avoid if, for example
fullOuterJoin xs [] = [(Just x, Nothing) | x <- xs]
fullOuterJoin [] ys = [(Nothing, Just y) | y <- ys]
fullOuterJoin xss#(x:xs) yss#(y:ys) =
case (compare `on` key) x y of
EQ -> (Just x, Just y): fullOuterJoin xs ys
LT -> (Just x, Nothing): fullOuterJoin xs yss
GT -> (Nothing, Just y): fullOuterJoin xss ys
I can not think of any standard function doing this operation. I would convert the two lists into Data.Map.Maps and code the SQL-join myself. In this way, it looks doable with O(n log n) complexity, which is not too bad.
If you care about performance, this is not the answer you are looking for.
No answer for a built-in function since you didn't give a type.
It can be done by a simple list comprehension
joinOnFst as bs = [(a,b) | a<-as, b<-bs, fst a == fst b]
or with pattern matching and a different return type
joinOnFst as bs = [(a1,a2,b2) | (a1,a2)<-as, (b1,b2)<-bs, a1==b1]
More abstract, you can define
listJoinBy :: (a -> b -> Bool) -> [a] -> [b] -> [(a,b)]
listJoinBy comp as bs = [(a,b) | a<-as, b<-bs, comp a b]
listJoin :: (Eq c) => (a -> c) -> (b -> c) -> [a] -> [b] -> [(a,b)]
listJoin fa fb = listJoinBy (\a b -> fa a == fb b)
I bet the last line can be made point-free or at least the lambda can be eliminated.
You're asking if there's a way to something like a SQL join in Haskell.
Rosetta code has an example in Haskell of how to do a hash join, which is the algorithm lots of RDBMS's use for JOINs, one of which is presented as cleaner (though it is slower):
a cleaner and more functional solution would be to use Data.Map (based on binary trees):
import qualified Data.Map as M
import Data.List
import Data.Maybe
import Control.Applicative
mapJoin xs fx ys fy = joined
where yMap = foldl' f M.empty ys
f m y = M.insertWith (++) (fy y) [y] m
joined = concat .
mapMaybe (\x -> map (x,) <$> M.lookup (fx x) yMap) $ xs
main = mapM_ print $ mapJoin
[(1, "Jonah"), (2, "Alan"), (3, "Glory"), (4, "Popeye")]
snd
[("Jonah", "Whales"), ("Jonah", "Spiders"),
("Alan", "Ghosts"), ("Alan", "Zombies"), ("Glory", "Buffy")]
fst
What you asked is basically
ordzip a#(x:t) b#(y:r) = case compare x y of
LT -> (Just x, Nothing) : ordzip t b
EQ -> (Just x, Just y) : ordzip t r
GT -> (Nothing, Just y) : ordzip a r
ordzip a [] = [(Just x, Nothing) | x <- a]
ordzip [] b = [(Nothing, Just y) | y <- b]
With it, we can further define e.g.
import Control.Applicative (<|>)
diff xs ys = [x | (Just x, Nothing) <- ordzip xs ys] -- set difference
meet xs ys = [y | (Just _, Just y) <- ordzip xs ys] -- intersection
union xs ys = [z | (u,v) <- ordzip xs ys, let Just z = u <|> v]
or have few variations concerning the access to keys or handling of duplicates etc. (like defining ordzipBy k a#(x:t) b#(y:r) = case compare (k x) (k y) of ...).
But this is better represented with Data.These.These type to explicate the fact that (Nothing, Nothing) can never happen:
import Data.These
ordzip a#(x:t) b#(y:r) = case compare x y of
LT -> This x : ordzip t b
GT -> That y : ordzip a r
_ -> These x y : ordzip t r
diff xs ys = catThis $ ordzip xs ys
meet xs ys = map snd . catThese $ ordzip xs ys -- or map fst, or id
union xs ys = map (mergeThese const) $ ordzip xs ys
Of course the input lists are to be sorted by the key beforehand.
Related
This is the code that I came upon somewhere but want to know how this works:
findIndices :: (a -> Bool) -> [a] -> [Int]
findIndices _ [] = []
findIndices pred xs = map fst (filter (pred . snd) (zip [0..] xs))
Output: findIndices (== 0) [1,2,0,3,0] == [2,4], where pred is (==0) & xs is [1,2,0,3,0]
I'll show some of my understanding:
(zip [0..] xs)
What the above line does is put indices to everything in the list. For the input given above, it would look like this: [(0,1),(1,2),(2,0),(3,3),(4,0)].
(pred . snd)
I found that this means something like pred (snd (x)). My question is, is x the list made from the zip line? I'm leaning towards yes but my guess is flimsy.
Next, is my understanding of fst and snd. I know that
fst(1,2) = 1
and
snd(1,2) = 2
How do these two commands make sense in the code?
My understanding of filter is that it returns a list of items that match a condition. For instance,
listBiggerThen5 = filter (>5) [1,2,3,4,5,6,7,8,9,10]
would give [6,7,8,9,10]
My understanding of map is that it applies a function to every item on the list. For instance,
times4 :: Int -> Int
times4 x = x * 4
listTimes4 = map times4 [1,2,3,4,5]
would give [4,8,12,16,20]
How does this work overall? I think I have been comprehensive in what I know so far but can't quite put the pieces together. Can anybody help me out?
I found that this means something like pred (snd (x)). My question is, is x the list made from the zip line? I'm leaning towards yes but my guess is flimsy.
Well pred . snd, means \x -> pred (snd x). So this basically constructs a function that maps an element x on pred (snd x).
This thus means that the expression looks like:
filter (\x -> pred (snd x)) (zip [0..] xs)
Here x is thus a 2-tuple generated by zip. So in order to know if (0, 1), (1,2), (2, 0), etc. are retained in the result, snd x will take the second element of these 2-tuples (so 1, 2, 0, etc.), and check if the pred on tha element is satisfied or not. If it is satisfied, it will retain the element, otherwise that element (the 2-tuple) is filtered out.
So if (== 0) is the predicate, then filter (pred . snd) (zip [0..] xs) will contain the 2-tuples [(2, 0), (4, 0)].
But now the result is a list of 2-tuples. If we want the indices, we somehow need to get rid of the 2-tuple, and the second element of these 2-tuples. We use fst :: (a, b) -> a for that: this maps a 2-tuple on its first element. So for a list [(2, 0), (4, 0)], map fst [(2, 0), (4, 0)] will return [2, 4].
In Haskell we like to say, follow the types. Indeed the pieces connect as if by wires going from type to corresponding type:
( first, function composition is:
(f >>> g) x = (g . f) x = g (f x)
(f >>> g) = (g . f) = \x -> g (f x)
and function composition type inference rule is:
f :: a -> b -- x :: a
g :: b -> c -- f x :: b
------------------------- -- g (f x) :: c
f >>> g :: a -> c
g . f :: a -> c
Now, )
findIndices :: (b -> Bool) -> [b] -> [Int]
findIndices pred = \xs -> map fst ( filter (pred . snd) ( zip [0..] xs ))
= map fst . filter (pred . snd) . zip [0..]
= zip [0..] >>> filter (snd >>> pred) >>> map fst
---------------------------------------------------------------------------
zip :: [a] -> [b] -> [(a, b)]
zip [0..] :: [b] -> [(Int,b)]
---------------------------------------------------------------------------
snd :: (a,b) -> b
pred :: b -> Bool
------------------------------------
(snd >>> pred) :: (a,b) -> Bool
---------------------------------------------------------------------------
filter :: (t -> Bool) -> [t] -> [t]
filter (snd >>> pred) :: [(a,b)] -> [(a,b)]
filter (snd >>> pred) :: [(Int,b)] -> [(Int,b)]
---------------------------------------------------------------------------
fst :: (a, b) -> a
map :: (t -> s) -> [t] -> [s]
map fst :: [(a,b)] -> [a]
map fst :: [(Int,b)] -> [Int]
so, overall,
zip [0..] :: [b] -> [(Int,b)]
filter (snd >>> pred) :: [(Int,b)] -> [(Int,b)]
map fst :: [(Int,b)] -> [Int]
---------------------------------------------------------------------------
findIndices pred :: [b] -> [Int]
You've asked, how do these pieces fit together?
This is how.
With list comprehensions, your function is written as
findIndices pred xs = [ i | (i,x) <- zip [0..] xs, pred x ]
which in pseudocode reads:
"result list contains i for each (i,x) in zip [0..] xs such that pred x holds".
It does this by turning the n-long
xs = [a,b,...,z] = [a] ++ [b] ++ ... ++ [z]
into
[0 | pred a] ++ [1 | pred b] ++ ... ++ [n-1 | pred z]
where [a | True] is [a] and [a | False] is [].
I'm writing a function that takes a list and two elements that can possibly be contained in the list. The function should return the two elements in a structure that sorts them by their occurrence in the list.
So, for number we'd have something like this:
xs = [4,6,3,2,1,8]
f (3,1) --> (Just 3, Just 1)
f (1,3) --> (Just 3, Just 1)
f (9,1) --> (Just 1, Nothing)
f (9,9) --> (Nothing, Nothing)
and so on..
I used tuples up there since I'm actually only interested in those two values instead of an arbitrary number. But if there are reasons, modeling it as list would be ok as well.
Anyways, here's the function I came up with:
f :: Eq a => [a] -> (a, a) -> (Maybe a, Maybe a)
f xs (a, b) = foldl g (Nothing, Nothing) xs where
g (Nothing, Nothing) x | x == a = (Just a, Nothing)
g (Nothing, Nothing) x | x == b = (Just b, Nothing)
g (Just a', Nothing) x | a' == a && x == b = (Just a, Just b)
g (Just b', Nothing) x | b' == b && x == a = (Just b, Just a)
g m x = m
Its working, but I think it's quite a lot of pattern matching in there, it's sort of error-prone. So, does anybody have a better abstraction for the problem?
If you want to decrease number of pattern matchings then it's better to never pass pair (Maybe a, Maybe a) recursively and pattern match on it. You can just split your function into two recursive functions where first functions finds first element and calls second function with the other. This can be done like this:
f :: Eq a => (a, a) -> [a] -> (Maybe a, Maybe a)
f (a, b) = goFirst
where
goFirst [] = (Nothing, Nothing)
goFirst (x:xs)
| x == a = (Just a, goSecond b xs)
| x == b = (Just b, goSecond a xs)
| otherwise = goFirst xs
goSecond _ [] = Nothing
goSecond y (x:xs)
| x == y = Just y
| otherwise = goSecond y xs
This is not so short and elegant as you may want but it's readable, fast (I want to add that you should never ever use foldl function) and less error-prone.
If you're looking for some abstractions, you may look at First monoid with pair monoid. Using monoid instance for First data type you can start with something like this:
import Data.Bifunctor (bimap)
import Data.Monoid (First (..), mconcat)
g :: Eq a => (a, a) -> [a] -> (Maybe a, Maybe a)
g (a, b) = bimap getFirst getFirst . mconcat . map fMapper
where
fMapper x
| x == a = (First (Just a), mempty)
| x == b = (mempty, First (Just b))
| otherwise = mempty
Though this function doesn't do exactly what you want:
ghci> let xs = [4,6,3,2,1,8]
ghci> g (3, 1) xs
(Just 3,Just 1)
ghci> g (1, 3) xs
(Just 1,Just 3)
To achieve initial goal with this approach you can add indices to each element and then sort pairs under First by indices but this solution is scary and ugly. Using First monoid is tempting but I don't know how it can be used here elegantly.
But you can combine ideas from first and second solutions:
import Data.Bool (bool)
import Data.Monoid (First (..))
h :: Eq a => (a, a) -> [a] -> (Maybe a, Maybe a)
h (a, b) = goFirst
where
goFirst [] = (Nothing, Nothing)
goFirst (x:xs)
| x == a = (Just a, goSecond b xs)
| x == b = (Just b, goSecond a xs)
| otherwise = goFirst xs
goSecond y = getFirst . foldMap (bool mempty (First (Just y)) . (== y))
Here’s one possible solution with lists, of the following type:
f :: Eq a => [a] -> [a] -> [Maybe a]
I’ll call the list to be searched the haystack and the elements to search for the needles. First, we can search the haystack for each needle and return a pair of the value and the index where it was found, if any, using findIndex:
findIndices needles haystack =
[ (needle, findIndex (== needle) haystack)
| needle <- needles
]
findIndices [1, 3] xs == [(1, Just 4), (3, Just 2)]
(Note that this always uses the index of the first occurrence—I’m not sure if that’s what you want. You can extend this into a fold that removes each occurrence as it’s found.)
Then sort this list by the index:
sortBy (comparing snd) [(1, Just 4), (3, Just 2)]
==
[(3, Just 2), (1, Just 4)]
And finally extract the value for each index that was actually present, using (<$) :: Functor f => a -> f b -> f a:
[value <$ mIndex | (value, mIndex) <- [(3, Just 2), (1, Just 4)]]
==
[Just 3, Just 1]
(x <$ f is equivalent to const x <$> f.)
But when we try this on an input where some elements aren’t found, we get the wrong result, where the Nothings come at the beginning rather than the end:
findIndices [9, 1] xs == [(9, Nothing), (1, Just 4)]
sortBy (comparing snd) [(9, Nothing), (1, Just 4)]
==
[(9, Nothing), (1, Just 4)]
This is because Nothing is considered less than any Just value. Since we want the opposite, we can reverse the sort order of the Maybe using the Down newtype from Data.Ord, by passing Down . snd instead of snd as the comparator:
sortBy (comparing (Down . snd)) [(9, Nothing), (1, Just 4)]
==
[(1, Just 4), (9, Nothing)]
But this also reverses the sort order of the indices themselves, which we don’t want:
sortBy (comparing (Down . snd)) [(1, Just 4), (3, Just 2)]
==
[(1, Just 4), (3, Just 2)]
So we can just add another Down around the indices:
findIndices needles haystack =
[ (needle, Down <$> findIndex (== needle) haystack)
| needle <- needles
]
sortBy (comparing Down) [Just (Down 2), Nothing, Just (Down 1)]
==
[Just (Down 1), Just (Down 2), Nothing]
sortBy (comparing (Down . snd))
[(1, Down (Just 4)), (3, Down (Just 2))]
==
[(3, Down (Just 2)), (1, Down (Just 4))]
And finally put it all together:
f :: (Eq a) => [a] -> [a] -> [Maybe a]
f needles haystack =
[ value <$ index
| (value, index) <- sortBy (comparing (Down . snd))
[ (needle, Down <$> findIndex (== needle) haystack)
| needle <- needles
]
]
f [1, 3] xs == [Just 3, Just 1]
f [3, 1] xs == [Just 3, Just 1]
f [1, 9] xs == [Just 1, Nothing]
f [9, 9] xs == [Nothing, Nothing]
Or, without list comprehensions and with shorter names:
f :: (Eq a) => [a] -> [a] -> [Maybe a]
f ns hs
= map (\ (v, i) -> v <$ i)
$ sortBy (comparing (Down . snd))
$ map (\ n -> (n, Down <$> findIndex (== n) hs)) ns
\ (v, i) -> v <$ i can also be written as uncurry (<$), but that might be a bit cryptic if you’re not accustomed to point-free style. In addition, if you don’t care about the Nothings, you can use mapMaybe instead of map, changing the return type from [Maybe a] to just [a].
I don't know how much better you will think these are, but you can do some things making more use of list functions.
I initially thought of filtering out the irrelevant
items first, and grouping:
f :: Eq a => [a] -> (a,a) -> (Maybe a, Maybe a)
f xs (a, b) =
case (map head . group . filter (`elem` [a,b])) xs of
[] -> (Nothing, Nothing)
[c] -> (Just c, Nothing)
(c:d:_) -> (Just c, Just d)
But this doesn't do the same as your implementation on, for example,
f [8,9,9] (9,9), so you'd need to special-case that if it's a case
you care about.
Another way is with dropWhile:
f' :: Eq a => [a] -> (a,a) -> (Maybe a, Maybe a)
f' xs (a, b) =
case dropWhile (`notElem` [a, b]) xs of
[] -> (Nothing, Nothing)
(y:ys) -> (Just y, next)
where
next = case dropWhile (/=other) ys of
[] -> Nothing
(z:_) -> Just z
other = if y == a then b else a
And the inner case is really just a find so it can be simplified a
little more:
f'' :: Eq a => [a] -> (a,a) -> (Maybe a, Maybe a)
f'' xs (a, b) =
case dropWhile (`notElem` [a, b]) xs of
[] -> (Nothing, Nothing)
(y:ys) -> (Just y, find (==other) ys)
where
other = if y == a then b else a
Note: these functions never return a result of the form (Nothing, Just _). This suggests that a return type of Maybe (a, Maybe a)
might be better. Or a custom type like None | One a | Two a a.
Alternatively, we could generalize to a list version which allows as
many target values as you like. It makes a nice unfold:
f''' :: Eq a => [a] -> [a] -> [a]
f''' xs ts = unfoldr g (xs, ts)
where
g (ys, us) = case dropWhile (`notElem` us) ys of
[] -> Nothing
(z:zs) -> Just (z, (zs, delete z us))
Which works like this:
λ> f''' [4,2,5,3,1] [1,2,3]
[2,3,1]
λ> f''' [4,2,5,3,1] [1,2,6]
[2,1]
λ> f''' [7,9,8,9] [9,9]
[9,9]
I'm almost reinventing intersect here but not quite. It has the behaviour we want of preserving the order from the first list, but it isn't the same on duplicates - e.g. intersect [4,2,2,5] [1,2] is [2,2].
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]]
I want to take a list (or a string) and split it into sub-lists of N elements. How do I do it in Haskell?
Example:
mysteryFunction 2 "abcdefgh"
["ab", "cd", "ef", "gh"]
cabal update
cabal install split
And then use chunksOf from Data.List.Split
Here's one option:
partition :: Int -> [a] -> [[a]]
partition _ [] = []
partition n xs = (take n xs) : (partition n (drop n xs))
And here's a tail recursive version of that function:
partition :: Int -> [a] -> [[a]]
partition n xs = partition' n xs []
where
partition' _ [] acc = reverse acc
partition' n xs acc = partition' n (drop n xs) ((take n xs) : acc)
You could use:
mysteryFunction :: Int -> [a] -> [[a]]
mysteryFunction n list = unfoldr takeList list
where takeList [] = Nothing
takeList l = Just $ splitAt n l
or alternatively:
mysteryFunction :: Int -> [a] -> [[a]]
mysteryFunction n list = unfoldr (\l -> if null l then Nothing else Just $ splitAt n l) list
Note this puts any remaining elements in the last list, for example
mysteryFunction 2 "abcdefg" = ["ab", "cd", "ef", "g"]
import Data.List
import Data.Function
mysteryFunction n = map (map snd) . groupBy ((==) `on` fst) . zip ([0..] >>= replicate n)
... just kidding...
mysteryFunction x "" = []
mysteryFunction x s = take x s : mysteryFunction x (drop x s)
Probably not the elegant solution you had in mind.
There's already
Prelude Data.List> :t either
either :: (a -> c) -> (b -> c) -> Either a b -> c
and
Prelude Data.List> :t maybe
maybe :: b -> (a -> b) -> Maybe a -> b
so there really should be
list :: t -> ([a] -> t) -> [a] -> t
list n _ [] = n
list _ c xs = c xs
as well. With it,
import Data.List (unfoldr)
g n = unfoldr $ list Nothing (Just . splitAt n)
without it,
g n = takeWhile (not.null) . unfoldr (Just . splitAt n)
A fancy answer.
In the answers above you have to use splitAt, which is recursive, too. Let's see how we can build a recursive solution from scratch.
Functor L(X)=1+A*X can map X into a 1 or split it into a pair of A and X, and has List(A) as its minimal fixed point: List(A) can be mapped into 1+A*List(A) and back using a isomorphism; in other words, we have one way to decompose a non-empty list, and only one way to represent a empty list.
Functor F(X)=List(A)+A*X is similar, but the tail of the list is no longer a empty list - "1" - so the functor is able to extract a value A or turn X into a list of As. Then List(A) is its fixed point (but no longer the minimal fixed point), the functor can represent any given list as a List, or as a pair of a element and a list. In effect, any coalgebra can "stop" decomposing the list "at will".
{-# LANGUAGE DeriveFunctor #-}
import Data.Functor.Foldable
data N a x = Z [a] | S a x deriving (Functor)
(which is the same as adding the following trivial instance):
instance Functor (N a) where
fmap f (Z xs) = Z xs
fmap f (S x y) = S x $ f y
Consider the definition of hylomorphism:
hylo :: (f b -> b) -> (c -> f c) -> c -> b
hylo psi phi = psi . fmap (hylo psi phi) . phi
Given a seed value, it uses phi to produce f c, to which fmap applies hylo psi phi recursively, and psi then extracts b from the fmapped structure f b.
A hylomorphism for the pair of (co)algebras for this functor is a splitAt:
splitAt :: Int -> [a] -> ([a],[a])
splitAt n xs = hylo psi phi (n, xs) where
phi (n, []) = Z []
phi (0, xs) = Z xs
phi (n, (x:xs)) = S x (n-1, xs)
This coalgebra extracts a head, as long as there is a head to extract and the counter of extracted elements is not zero. This is because of how the functor was defined: as long as phi produces S x y, hylo will feed y into phi as the next seed; once Z xs is produced, functor no longer applies hylo psi phi to it, and the recursion stops.
At the same time hylo will re-map the structure into a pair of lists:
psi (Z ys) = ([], ys)
psi (S h (t, b)) = (h:t, b)
So now we know how splitAt works. We can extend that to splitList using apomorphism:
splitList :: Int -> [a] -> [[a]]
splitList n xs = apo (hylo psi phi) (n, xs) where
phi (n, []) = Z []
phi (0, xs) = Z xs
phi (n, (x:xs)) = S x (n-1, xs)
psi (Z []) = Cons [] $ Left []
psi (Z ys) = Cons [] $ Right (n, ys)
psi (S h (Cons t b)) = Cons (h:t) b
This time the re-mapping is fitted for use with apomorphism: as long as it is Right, apomorphism will keep using hylo psi phi to produce the next element of the list; if it is Left, it produces the rest of the list in one step (in this case, just finishes off the list with []).
I want a function that takes two lists of any type and returns one (i.e. f:: [[a]] -> [[a]] -> [[a]]). Basically, too produce the 'concatenation' of the two input lists.
e.g.
> f [[1,2,3], [123]] [[4,5,6], [3,7]]
[[1,2,3,4,5,6], [1,2,3,3,7], [123,4,5,6], [123,3,7]]
I currently have got this far with it:
f _ [] = []
f [] _ = []
f (xs:xss) (ys:yss) = ((xs ++ ys) : [m | m <- f [xs] yss])
But this doesn't take into account xss and is wrong. Any suggestions?
It's a Cartesian product, so you can simply use one list comprehension to do everything.
Prelude> let xs = [[1,2,3], [123]]
Prelude> let ys = [[4,5,6], [3,7]]
Prelude> [x ++ y | x <- xs, y <- ys]
[[1,2,3,4,5,6],[1,2,3,3,7],[123,4,5,6],[123,3,7]]
import Control.Applicative
(++) <$> [[1,2,3], [123]] <*> [[4,5,6], [3,7]]
[[1,2,3,4,5,6],[1,2,3,3,7],[123,4,5,6],[123,3,7]]
f l1 l2 = [x ++ y | x <- l1, y <- l2]
In Alternative:
import Control.Applicative
f :: (Applicative f, Alternative g) => f (g a) -> f (g a) -> f (g a)
f = liftA2 (<|>)
f a b = map concat . sequence $ [a,b]
Scales up for combining any number of lists.