Search code examples
haskellfunctor

How to create functor instance for phantom type where first argument phantom?


One of the exercises in the http://haskellbook.com is to write a functor instance for

data EvilGoateeConst a b =
  GoatyConst b

My attempt is

instance Functor (EvilGoateeConst a) where
  fmap f (GoatyConst b) = GoatyConst b

The simplest fix is just to switch the arguments to the type constructor, but I guess that is verboten. What is the simplest way of fixing this without changing the original type?

(And I am not applying the function because that makes the compiler barf, but I think it still is a valid functor according to the laws.)


Solution

  • I think you are overthinking this problem - look at the type of fmap in this case it should be:

    fmap :: (b -> c) -> EvilGoateeConst a b -> EvilGoateeConst a c
    

    The reason is that EvilGoateeConst a b ~ (EvilGoateeConst a) b and so EvilGoateeConst a :: * -> * fits exactly the kind a Functor instance need to have but now the a is fixed and the functor might change the b instead


    ok I don't know how to say more without totally spoiling it so don't look if you want to try it yourself but the answer is just:

    instance Functor (EvilGoateeConst a) where
      fmap f (GoatyConst b) = GoatyConst (f b)