具有更高kinded类型的类型类约束

时间:2017-04-29 18:36:27

标签: haskell

我正在尝试为Eq新类型编写EitherT个实例,其中包含:

newtype EitherT e m a = EitherT { runEitherT :: m (Either e a) }

我假设以下Eq实例可行:

instance (Eq e, Eq a, Eq m) => Eq (EitherT e m a) where
  a == b = (runEitherT a) == (runEitherT b)

但是,我发现了一个错误:

Expected kind '* -> *', but 'm' has kind '*'

我从该错误中读到的是,我的类型类约束( ... Eq m) => ...让编译器误以为我认为m属于*,当我的新类型时EitherT的声明预计它是* -> *。{/ p>

我想知道我需要做什么,声明我想要一个Eq实例用于某些更高级别的m类型Eq来为EitherT实现{-# LANGUAGE UndecideableInstances #-} instance (Eq (m (Either e a))) => Eq (EitherT e m a) where a == b = (runEitherT a) == (runEitherT b) } newtype。

编辑正如@AlexisKing所指出的,我可以使用它:

Eq

然而,我觉得编写这个I0 = imread('1_2.jpg'); [R,C,K] = size(I0); if K==1 I1 = I0; else I1 = rgb2gray(I0); end T = adaptthresh(I1, 0.4); %adaptive thresholding % Convert image to binary image, specifying the threshold value. BW = imbinarize(I1,T); % Display the original image with the binary version, side-by-side. figure imshowpair(I1, BW, 'montage') 实例需要语言扩展似乎很奇怪。在vanilla Haskell中没有其他方法可以表达这样的类型类约束吗?如果没有,为什么?

2 个答案:

答案 0 :(得分:6)

您正在寻找自{4.9}以来Data.Functor.Classes以来的Eq1。在此之前,它位于-extras个包中的一个或transformers? (它是in transformers now since 0.4.0.0

Eq1 f表示您可以比较f只要您有办法比较其内容

class Eq1 f where
    liftEq :: (a -> b -> Bool) -> f a -> f b -> Bool

在您的情况下,您可以像

一样使用它
instance (Eq e, Eq1 m) => Eq1 (EitherT e m) where
   liftEq f a b = liftEq (liftEq f) (runEitherT a) (runEitherT b)

liftEq f是使用Eq1的现有Either个实例。

可以将Eq实例定义为

instance (Eq e, Eq a, Eq1 m) => Eq (EitherT e m a) where
   (==) = liftEq (==)

旧的Eq1

class Eq1 f where
    eq1 :: (Eq a) => f a -> f a -> Bool

在您的情况下,您可以像

一样使用它
instance (Eq e, Eq1 m) => Eq1 (EitherT e m) where
   eq1 a b = eq1 (runEitherT a) (runEitherT b)

instance (Eq e, Eq a, Eq1 m) => Eq1 (EitherT e m) where
   a == b = eq1 (runEitherT a) (runEitherT b)

答案 1 :(得分:2)

值得注意的是,此实例已存在于either包的当前版本中(尽管不是旧的EitherT包,这被认为是过时的):

instance Eq (m (Either e a)) => Eq (EitherT e m a) where
  (==) = (==) on runEitherT

当然,正如@Alexis King所说,它需要UndecidableInstances,但either包是由Edward Kmett创作的,他是臭名昭着的dilettante和业余爱好者,他们不能像我们一样编写适当的Haskell98 < em>真正的程序员。 ;)