Question

I have some datatype Verb p defined as such:

data Verb p =   Look          {getPreps :: p}
              | LookExtra     {getPreps :: p}
              | Touch         {getPreps :: p}
              | Smell         {getPreps :: p}
              | HearExtra     {getPreps :: p}
              | Hear          {getPreps :: p}
              | Taste         {getPreps :: p}
              | Pickup        {getPreps :: p}
              | PickupExtra   {getPreps :: p}
              | Move          {getPreps :: p}
              | MoveExtra     {getPreps :: p}
              deriving (Show,Ord,Eq)

I must make this datatype an instance of Functor at the very least. Hence:

instance Functor Verb where
  fmap f (Look a)        = Look (f a)
  fmap f (LookExtra a)   = LookExtra (f a)
  fmap f (Touch a)       = Touch (f a)
  fmap f (Smell a)       = Smell (f a)
  fmap f (HearExtra a)   = HearExtra (f a)
  fmap f (Hear a)        = Hear (f a)
  fmap f (Taste a)       = Taste (f a)
  fmap f (Pickup a)      = Pickup (f a)
  fmap f (PickupExtra a) = PickupExtra (f a)
  fmap f (Move a)        = Move (f a)
  fmap f (MoveExtra a)   = MoveExtra (f a)

If that isn't boilerplate, then I don't know what is. I can imagine this becoming a real pain if I have to progress to Applicative Functors and so on. Is there a better way to write this without changing the structure of Verb p altogether? Due to the way I have written Verb p, It seems like I am doomed to declare an instance for each datatype constructor. Hopefully I can be proven wrong.

Was it helpful?

Solution

Check out the DeriveFunctor extension. As the name hints, it allows you to simply add Functor to the deriving list. Unfortunately, this doesn't extend to Applicative and Monad because, unlike Functor, those generally don't have one way to define the instance, but multiple nonequivalent possibilities.

In your example, I'd simplify the data definition:

data VerbType = Look | LookExtra | ...
type Verb a = (VerbType, a)
-- or data Verb a = Verb { verbType :: VerbType, getPreps :: a }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top