Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make data type with kind *->*->* a functor

Tags:

haskell

I have this type:

data Move a t = Emove a a
              | Move a t a

and I wanted to make it a functor:

instance Functor Move where
    fmap f (Emove x y)  = Emove (f x) (f y)
    fmap f (Move x c y) = Move (f x) c (f y)

but this does not compile because of the wrong kind of this type. Could someone please help me resolve this? How to supply the type t to this instance?

like image 505
akonsu Avatar asked Jun 16 '26 23:06

akonsu


1 Answers

It would work better if you swapped the order of the type variables to Move:

data Move t a = Emove a a | Move a t a

Then you can define the functor as

instance Functor (Move t) where
    fmap f (Emove x y) = Emove (f x) (f y)
    fmap f (Move x c y) = Move (f x) c (f y)

Any type that is a functor must have kind * -> *, that's just how it's defined. Since you have a type that is * -> * -> *, you must make one of the type variables invariant under the functor (or else use a bifunctor, where the explicit purpose is to have a functor over both type variables). Since you want the a to change and not the t, Haskell requires that the a type variable come last, it's just how the syntax works. It's like with the Either type, the functor instance is Functor (Either a), but that's a pretty arbitrary definition, it only changes values with the Right constructor, whereas it could have equivalently been defined for values with the Left constructor. The meaning would be the same mathematically, but for consistency Haskell has enforced through syntax that the type variable that can change through the functor is the last type variable.

like image 80
bheklilr Avatar answered Jun 19 '26 15:06

bheklilr