在我写下面代码的地方,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并加载文件后,它成功编译.为什么?
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扩展.