如果我定义:
class Contravariant f where
contramap :: (b -> a) -> f a -> f b
type Op r a = (->) a r并且想要定义:
instance Contravariant (Op r) where
contramap f g = g . f我得到的错误是实例类型不能是同义词。所以我想我需要一些类似的东西:
instance Contravariant ((->) _ r) where
contramap f g = g . f这当然不起作用。我怎样才能让Contravariant的这个实例工作?
发布于 2021-01-06 05:15:03
根据注释,通常的方法是定义一个newtype。注意,语法与定义data类型非常相似,不同之处在于您使用newtype代替data,并且只允许使用一个字段。特别是,您需要一个构造函数,它通常被赋予与类型相同的名称:
newtype Op r a = Op (a -> r)
-- ^^ ^^ ^^^^^^^^
-- newtype constructor field这样做的效果是定义了一个与a -> r同构的类型,但类型参数a在完整类型Op r a中“最后”出现,这允许您为Op r定义一个Contravariant实例。请注意,您需要在适当的地方对构造函数进行解包和包装:
instance Contravariant (Op r) where
contramap f (Op g) = Op (g . f)要进一步证明这是正确的方法,请注意base中的Data.Functor.Contravariant中的definitions已经这样设置了,除非它们决定使用字段访问器getOp
-- from the Data.Functor.Contravariant source
newtype Op a b = Op { getOp :: b -> a }
instance Contravariant (Op a) where
contramap f g = Op (getOp g . f)https://stackoverflow.com/questions/65585918
复制相似问题