Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么Haskell中不允许此声明?_Haskell - Fatal编程技术网

为什么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“我没有做像上面那样愚蠢的事,相信我”。