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.

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top