我有一些数据类型Verb p
定义如下:
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)
我必须至少将此数据类型设为Functor
的实例。因此:
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)
如果那不是样板,那么我不知道是什么。我可以想象,如果我必须前进到Applicative Functors
等等,这将成为一种真正的痛苦。有没有更好的方法来编写它而不改变Verb p
的结构?由于我编写Verb p
的方式,似乎我注定要为每个数据类型构造函数声明一个实例。希望我被证明是错的。
答案 0 :(得分:12)
查看DeriveFunctor
扩展程序。如名称提示,它允许您只需将Functor
添加到deriving
列表中。不幸的是,这不会扩展到Applicative
和Monad
,因为与Functor
不同,这些通常没有一种方式来定义实例,但是多个非等价的可能性。
在您的示例中,我将简化数据定义:
data VerbType = Look | LookExtra | ...
type Verb a = (VerbType, a)
-- or data Verb a = Verb { verbType :: VerbType, getPreps :: a }