繁体   English   中英

使用类型生成数据类型* - > * - > *一个仿函数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM