为什么Haskell中不允许此声明?
我知道为什么Haskell中不允许此声明?,haskell,Haskell,我知道Functor和Applicative应该是Monad的超类,但不是出于历史原因。但是,为什么不能声明Monad一个Functor的实例?这将产生大致相同的效果,但不必修改现有代码。如果您试图这样做,GHC会抱怨: instance Functor Monad where fmap = liftM Class `Monad' used as a type In the instance declaration for `Functor Monad' 为什么呢?这可能有一个很好的理
Functor
和Applicative
应该是Monad
的超类,但不是出于历史原因。但是,为什么不能声明Monad
一个Functor
的实例?这将产生大致相同的效果,但不必修改现有代码。如果您试图这样做,GHC会抱怨:
instance Functor Monad where
fmap = liftM
Class `Monad' used as a type
In the instance declaration for `Functor Monad'
为什么呢?这可能有一个很好的理由。您的语法错误
Monad
是一个类型类,而不是数据类型。你能写的是
instance Monad a => Functor a where fmap = liftM
但是,这只适用于扩展名
FlexibleInstances
(允许不是ta1a2…an
形式的实例,其中a1,a2,…an
是类型变量,没有上下文)和不可判定的实例
(允许这个特定实例[我不知道为什么需要这个]).原因是Monad
是一个类型类,而实例声明需要类型或类型构造函数。错误消息清楚地表明。类型类和类型是两种截然不同的东西。它们在Haskell中永远不可交换。实例(Monad m)=>函子m如何?请参见以下答案:不可判定实例
是必需的,因为声明与明确定义为函子的每个Monad冲突,包括标准库中的所有Monad。嗯,我想,UndededicatableInstances
要求也回答了为什么在Prelude或另一个包中没有定义的问题…@dave4420编译器说,这是因为实例头比实例本身大。。。我不明白。此外,有人建议更改单子的定义,以包括函子和applicative.dave4420是不正确的:冲突的声明将意味着重叠实例
或不连贯
。这需要不可判定实例
的原因如下:当检查Foo
是否为函子
时,此规则意味着我们必须检查Foo
是否为单子
——也就是说,我们必须使用不小于我们开始使用的类型递归到实例查找算法中。如果我们允许这种递归,就很容易编写永不停止递归的实例,而如果类型在每一步都必须变小,则显然是不可能的。想象一下,如果一个实例同时定义了实例Functor a=>Monad a
(别介意你不能定义任何方法,typechecker不知道这一点)<代码>不可判定的实例你是在告诉GHC“我没有做像上面那样愚蠢的事,相信我”。