Is it possible to map tuple of functions over a list in Haskell?
-
12-12-2019 - |
Question
I'm trying to do find a way to do something like this:
(head, last) `someFunction` [1, 2, 3]
to produce the tuple (1, 3)
as output.
It seems similar in theory to an applicative functor, but a little backwards. I'm guessing there's a similar function that does this (or some way to make one), but I can't seem to find it/figure it out.
I tried defining a function like this:
fmap' :: ((a -> b), (a -> b)) -> [a] -> (b, b)
fmap' (f1, f2) xs = (f1 xs, f2 xs)
but GHC won't actually compile this.
Any help would be great; thanks!
Edit (a whole year later!):
My fmap'
wouldn't compile because the type signature was wrong. Obviously there are better ways to do what I was doing, but the type of my fmap'
should instead be:
fmap' :: ((a -> b), (a -> b)) -> a -> (b, b)
In that case, it compiles and runs just fine.
Solution
I think you can do this with arrows.
head &&& last $ [1,2,3]
will return (1,3)
.
OTHER TIPS
It seems similar in theory to an applicative functor, but a little backwards.
Actually, it's a boring old forwards applicative functor; specifically, the reader ((->) r)
.
Prelude Control.Applicative> liftA2 (,) head last [1,2,3]
(1,3)
Or, if you're into that kind of thing:
Prelude Control.Applicative> let sequenceA [] = pure []; sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
Prelude Control.Applicative> [head, last] `sequenceA` [1,2,3]
[1,3]
The type of fmap'
is wrong. It should be
fmap' :: ([a] -> b, [a] -> b) -> [a] -> (b, b)
or, it can be more generalized
fmap' :: (a -> b, a -> c) -> a -> (b, c)
It doesn't really resemble fmap :: (a -> b) -> f a -> f b
.
Something to try in this situation is to omit the type signature and check what GHC infers.
Doing so and asking GHCi :t fmap'
yields the signature
fmap' :: (t2 -> t, t2 -> t1) -> t2 -> (t, t1)
which is identical to KennyTM's generalized version, and will give you the behaviour you're looking for.