在我编写以下代码的地方,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)
编译器输出:
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)'
在我使用" ghci -XFlexibleInstances"启动ghci并加载文件,它成功编译。为什么呢?
答案 0 :(得分:6)
The Haskell Report restricts允许在类型类实例中显示的内容(默认情况下)
(第4.3.2节)......类型
(T u1 … uk)
必须采用应用于简单类型变量T
的类型构造函数u1, … uk
的形式;此外,T
不能是类型同义词,ui
必须全部不同。
松散地翻译,允许实例应用于类型构造函数(不是同义词,所以像List
,Maybe
,甚至像Int
这样的类似的东西),只要所有参数都传递给构造函数是唯一的类型变量。
在您的情况下,Gang
是类型构造函数,但String
不是类型变量。它甚至不是一个类型构造函数!它是具体类型[Char]
的类型同义词。
事实证明这是过于严格的限制。放松对所有传递的参数作为变量的需求是有意义的。允许类型同义词甚至有意义。但是,由于这些松弛不是标准化的,因此要求您传递LANGUAGE
编译指示或编译器标记以指示您使用非标准扩展。
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
通常,这些编译指示评论是非常优选的,因为非标准Haskellism的使用发生在特定文件中。您也可以同时指出所需的Haskell扩展。