Haskell function from (a -> [b]) -> [a -> b]
You can generalize seperateFuncs
to Applicative
(or Monad
) pretty cleanly:
seperateFuncs :: (Applicative f) => f (a -> b) -> (a -> f b)
seperateFuncs f x = f <*> pure x
Written in point-free style, you have seperateFuncs = ((. pure) . (<*>))
, so you basically want unap . (. extract)
, giving the following definition if you write it in pointful style:
joinFuncs :: (Unapplicative f) => (a -> f b) -> f (a -> b)
joinFuncs f = unap f (\ g -> f (extract g))
Here I define Unapplictaive
as:
class Functor f => Unapplicactive f where
extract :: f a -> a
unap :: (f a -> f b) -> f (a -> b)
To get the definitions given by leftaroundabout, you could give the following instances:
instance Unapplicative [] where
extract = head
unap f = [\a -> f [a] !! i | i <- [0..]]
instance Unapplicative ((->) c) where
extract f = f undefined
unap f = \x y -> f (const y) x
I think it's hard to come up with a "useful" function f :: (f a -> f b) -> f (a -> b)
for any f
that isn't like (->)
.
First of all, you can brute-force yourself this function all right:
joinFuncs f = [\x -> f x !! i | i<-[0..]]
but this is obviously troublesome – the resulting list is always infinite but evaluating the i
th element with x
only succeds if length(f x) > i
.
To give a "real" solution to
The question then is there some datatype
f
which has a function:: (a -> f b) -> f (a -> b)
?
Consider (->)c
. With that, your signature reads (a -> (c->b)) -> (c->(a->b))
or equivalently (a -> c -> b) -> c -> a -> b
which, it turns out, is just flip
.
Of course, this is a bit of a trivial one since seperateFuncs
has the same signature for this type...
"Is there some datatype f which has a function :: (a -> f b) -> f (a -> b)?"
In fact, there is an even more general version of this function in the Traversable type class, which deals with commutable functors:
class (Functor t, Foldable t) => Traversable t where
...
sequenceA :: Applicative f => t (f b) -> f (t b)
How is this related to your function? Starting from your type, with one type substitution, we recover sequenceA
:
(a -> f b) -> f (a -> b)
==>let t = (->) a
t (f b) -> f (t b)
However, this type has the constraint that t
must be a Traversable -- and there isn't a Traversable instance for (->) a
, which means that this operation can't be done in general with functions. Although note that the "other direction" -- f (a -> b) -> (a -> f b)
works fine for all functions and all Applicatives f
.