Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functors and Applicatives for types of kind (* -> *) -> *

Tags:

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 HFunctorin 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?

like image 879
shang Avatar asked Aug 05 '13 06:08

shang


People also ask

What are functors Applicatives and monads?

A functor is a data type that implements the Functor typeclass. An applicative is a data type that implements the Applicative typeclass. A monad is a data type that implements the Monad typeclass. A Maybe implements all three, so it is a functor, an applicative, and a monad.

What are functors in functional programming?

In functional programming, a functor is a design pattern inspired by the definition from category theory, that allows for a generic type to apply a function inside without changing the structure of the generic type. This idea is encoded in Haskell using type class.

What are functors used for Haskell?

Functor in Haskell is a typeclass that provides two methods – fmap and (<$) – for structure-preserving transformations. To implement a Functor instance for a data type, you need to provide a type-specific implementation of fmap – the function we already covered.

Are all monads applicative functors?

Every Monad is an Applicative Just as IO , every monad can be made into an applicative functor.


1 Answers

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.

like image 168
sclv Avatar answered Sep 27 '22 17:09

sclv