[英]make data type with kind *->*->* a functor
我有这种类型:
data Move a t = Emove a a
| Move a t a
我想把它变成一个仿函数:
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)
但由于这种类型的错误,这不能编译。 有人可以帮我解决这个问题吗? 如何为这个实例提供类型t
?
如果将类型变量的顺序交换为Move
它会更好用:
data Move t a = Emove a a | Move a t a
然后你可以将仿函数定义为
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)
任何作为仿函数的类型都必须具有类型* -> *
,这就是它的定义方式。 由于你的类型是* -> * -> *
,你必须在仿函数下使其中一个类型变量不变(或者使用bifunctor,其中明确的目的是在两个类型变量上都有一个仿函数)。 既然你想要a
改变而不是t
,Haskell要求a
类型变量最后,它就是语法的工作原理。 就像使用Either
类型一样,functor实例是Functor (Either a)
,但这是一个非常随意的定义,它只使用Right
构造函数更改值,而它可以等效地使用Left
构造函数为值定义。 数学意义相同,但为了保持一致性Haskell通过语法强制执行,可以通过仿函数更改的类型变量是最后一个类型变量。
您可以考虑将其改为Bifunctor
:
instance Bifunctor Move where
bimap f g (EMove a a') = EMove (f a) (f a')
bimap f g (Move a t a') = Move (f a) (g t) (f a')
然后,操作first f
将执行您希望fmap f
执行的操作。
简而言之:你做不到。 Functor
仅在一种类型上进行参数化。
因此,您只能使其成为Functor
类型的Functor
实例,部分应用:
instance Functor (Move a) where
您可以交换类型变量,使其在您的定义中对其他变量进行参数化。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.