如何在需要类型构造函数而不是具体类型的类的实例中满足类约束?

Mig*_*uel 16 haskell type-constructor

我目前在第8章学习,你一个Haskell,和我已经达成了部分Functor类型类.在上述部分中,作者给出了如何使不同类型成为类的实例(例如Maybe,自定义Tree类型等)的示例.看到这一点,我决定(为了乐趣和实践)尝试为该Data.Set类型实现实例; Data.Set.map当然,在所有这些忽视中.

实际的实例本身很简单,我把它写成:

instance Functor Set.Set where
  fmap f empty = Set.empty
  fmap f s = Set.fromList $ map f (Set.elems s)  
Run Code Online (Sandbox Code Playgroud)

但是,因为我碰巧使用的功能fromList,它可以提供一个类约束呼吁在使用的类型SetOrd,因为是由编译器错误解释:

Error occurred
ERROR line 4 - Cannot justify constraints in instance member binding
*** Expression    : fmap
*** Type          : Functor Set => (a -> b) -> Set a -> Set b
*** Given context : Functor Set
*** Constraints   : Ord b
Run Code Online (Sandbox Code Playgroud)

请参阅:实例

我尝试在实例上添加约束,或者添加类型签名fmap,但都没有成功(两者都是编译器错误.)

鉴于这种情况,如何实现约束并满足约束?有什么办法吗?

提前致谢!:)

Tik*_*vis 15

不幸的是,使用标准类没有简单的方法Functor.这就是为什么Set不拿出一个Functor默认实例:你不能写一个.

这是一个问题,并且有一些建议的解决方案(例如Functor以不同的方式定义类),但我不知道是否就如何最好地处理这个问题达成共识.

我相信一种方法是Functor使用约束种类重写类来重新定义新Functor类可能具有的附加约束实例.这将允许您指定Set必须包含类中的Ord类型.

另一种方法仅使用多参数类.我只能在Monad课堂上找到关于这样做的文章,但是让Set部分Monad面孔成为同样的问题Functor.它被称为受限制的Monads.

在这里使用多参数类的基本要点似乎是这样的:

class Functor' f a b where
  fmap' :: (a -> b) -> f a -> f b

instance (Ord a, Ord b) => Functor' Data.Set.Set a b where
  fmap' = Data.Set.map
Run Code Online (Sandbox Code Playgroud)

从本质上讲,你在这里所做的是使该类型Set类的也有一部分.然后,这可以让您在编写该类的实例时约束这些类​​型的内容.

这个版本Functor需要两个扩展:MultiParamTypeClassesFlexibleInstances.(您需要第一个扩展才能定义类,第二个扩展能够为其定义实例Set.)

Haskell:一个Foldable的例子,它不是Functor(或者不是Traversable)?对此有一个很好的讨论.

  • 受限函子类的一个问题是我们失去了很多权力.特别是对于applicative functor,我们经常想要将函数放入其中.但是,在许多情况下,不可能提供我们对函数感兴趣的类的一般实例. (6认同)