为什么"实例Monad(Gang String)在哪里"编译错误

Guo*_*eng 2 haskell typeclass

在我写下面代码的地方,Haskell不会编译.

data Gang b a=Gang{getGang::(a,b)}
instance Monad (Gang String) where
    return x        =   Gang (x,"")
    (Gang(x,log)) >>=f =   let Gang(x1,log1)= f x in Gang(x1,log++log1)
Run Code Online (Sandbox Code Playgroud)

编译器输出:

Illegal instance declaration for `Monad (Gang String)'
  (All instance types must be of the form (T a1 ... an)
   where a1 ... an are *distinct type variables*,
   and each type variable appears at most once in the instance head.
   Use -XFlexibleInstances if you want to disable this.)
In the instance declaration for `Monad (Gang String)'
Run Code Online (Sandbox Code Playgroud)

在我使用"ghci -XFlexibleInstances"启动ghci并加载文件后,它成功编译.为什么?

J. *_*son 6

Haskell报告限制允许在类型类实例中出现的内容(默认情况下)

(第4.3.2节)......类型(T u1 … uk)必须采用T应用于简单类型变量的类型构造函数的形式u1, … uk; 此外,T不能是类型的同义词,并且ui必须是不同的.

松散地翻译,只要传递给构造函数的所有参数都是唯一的类型变量,就允许实例应用于类型构造函数(不是同义词,所以类似的东西List,Maybe甚至是类似的东西Int).

在您的情况下,Gang是一个类型构造函数,但String不是一个类型变量.它甚至不是一个类型构造函数!它是具体类型的类型同义词[Char].

事实证明,这是过于严格的限制.放松对所有传递的参数作为变量的需求是有意义的.允许类型同义词甚至是有意义的.但是,由于这些松弛不是标准化的,因此需要传递LANGUAGE编译指示或编译器标志以指示您使用非标准扩展.

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
Run Code Online (Sandbox Code Playgroud)

通常,这些编译指示评论是非常优选的,因为非标准Haskellism的使用发生在特定文件中.您也可以同时指出所需的Haskell扩展.

  • [`TypeSynonymInstances`由`FlexibleInstances`暗示](http://www.haskell.org/ghc/docs/latest/html/users_guide/flag-reference.html#idp14615552).(有些东西告诉我,列表并没有给出所有含义.在某处有完整的列表吗?) (2认同)