Reputation: 436
I'm trying to figure out how to create a custom unzip function in Haskell using a custom version of fold (basically works as foldl) but I've become stuck. I can get it to
unzip' :: [(a,b)] -> ([a],[b])
unzip' = fold (\x->([x!!0],[x!!1])) ([],[])
But that errors out with:
• Couldn't match expected type ‘[a]’
with actual type ‘(Integer, Integer)’
• In the first argument of ‘tail’, namely ‘(1, 2)’
In the expression: tail (1, 2)
In an equation for ‘it’: it = tail (1, 2)
• Relevant bindings include
it :: [a] (bound at <interactive>:114:1)
From what I figure, x
is (1,2)
but I'm not sure how to further split it into 1 and 2. Here is the fold function that I am using:
fold :: (a -> b -> b) -> b -> ([a] -> b)
fold c n =
let f [] = n
f (x:xs) = x `c` (f xs)
in f
Thank you
Upvotes: 1
Views: 1261
Reputation: 8987
There are several issues with your lambda function.
Firstly, fold
expects a (a -> b -> b)
, so technically, a function with two arguments. Right now, your lambda only accepts 1 argument. Since your fold
resembles foldr
(folds from the right), the second argument should be the accumulator object, which collects the result from each fold.
Secondly, you are working with tuples, not lists (as pdexter noted in a comment). Thus, you should use the fst
and snd
functions.
After some modifications to the lambda:
\x acc -> (fst x:fst acc, snd x:snd acc)
This will append the first element from each tuple to the first list of the accumulator. And the second element from each tuple to the second list of the accumulator. Some results:
unzip' :: [(a,b)] -> ([a],[b])
unzip' = fold (\x acc -> (fst x:fst acc, snd x:snd acc)) ([],[])
unzip' [(1, 'a'), (2, 'b'), (3, 'c')]
([1,2,3],"abc")
Following Jon's comment, you can also take advantage of pattern matching in the lambda, replacing fst
and snd
. This may increase the strictness of the function. You can also replace ([], [])
with mempty
, a predefined empty tuple.
unzip' = fold (\(x, y) (xs, ys) -> (x:xs, y:ys)) mempty
Tip: Before jumping into the unzip
function, you could isolate and test out the lambda with your fold
first.
Upvotes: 5