Functors and Applicatives for types of kind (* -> *) -> *
applicative, functor, haskell, higher-kinded-types
Solution
The HFunctor I tend to think of is `(* -> *) -> * -> *` -- i.e. a legitimate functor on functors. This has different characteristics than the one you're thinking of.
Here's how to define it, as well as the "monoidal" version of an applicative on it.
type Nat f g = forall a. f a -> g a
class HFunctor (f :: (* -> *) -> * -> *) where
hfmap :: (Nat g h) -> Nat (f g) (f h)
data Prod f g a = Prod (f a) (g a)
class HFunctor f => HApplicative f where
hpure :: Nat g (f g)
htensor :: Nat (Prod (f g) (f h)) (f (Prod g h))
I'll try to update later with some ideas about what this is and how to use it.
This isn't exactly what you're asking for, I realize, but I was inspired to try it out by your post.
I'd be interested in your specific use case as well.
To your two specific questions A) The HFunctor you describe has been described before on various occasions, I think by Gibbons in particular, but I don't know of it packaged up. I certainly haven't seen the Applicative before. B) I think you're stuck with the wrapper because we can't partially apply type synonyms.
Problem
I ran into a situation where my code would benefit from using `Functor` and `Applicative` -like abstractions, but for types of kind `(* -> *) -> *`. Defining a higher-kinded functor can be done with `RankNTypes` like this ``` class HFunctor f where hfmap :: (forall x. a x -> b x) -> f a -> f b ``` But the higher kind version of `Applicative` is a bit trickier. This is the best I could come up with: ``` class HFunctor f => HApplicative f where hpure :: (forall x. a x) -> f a (<**>) :: f (a :-> b) -> f a -> f b newtype (:->) a b x = HFunc (a x -> b x) infixr 5 :-> ``` We need the `:->` wrapper type in order to have functions with the kind `* -> *`, but this doesn't let us nicely chain function application like we can with `<$>` and `<*>` for normal Applicatives. I can manage with helper such as ``` liftHA2 :: HApplicative f => (forall x. a x -> b x -> c x) -> f a -> f b -> f c liftHA2 f fa fb = hpure (fun2 f) <**> fa <**> fb where fun2 = HFunc . (HFunc .) ``` But it would be nice to have a general way to "lift" functions of any arity. Some simple examples how the above instances can be used: ``` data Example f = Example (f Int) (f String) instance HFunctor Example where hfmap f (Example i s) = Example (f i) (f s) instance HApplicative Example where hpure a = Example a a Example (HFunc fi) (HFunc fs) <**> Example i s = Example (fi i) (fs s) e :: Example [] e = Example [1,2,3] ["foo", "bar"] e' :: Example ((,) Int) e' = hfmap (length &&& head) e -- Example (3,1) (2, "foo") e'' :: Example [] e'' = liftHA2 (++) e e -- Example [1,2,3,1,2,3] ["foo", "bar", "foo", "bar"] ``` So, my question is: what are the above typeclasses called and are they already provided by some library in hackage? By googling I came up with `Functor2` in `linear-maps` and `HFunctor`in `multi-rec` but neither does exactly what I need. Also, is there some way to write `HApplicative` without the `:->` wrapper or some other way to make function lifting easier?