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

时间:2014-06-18 03:26:14

标签: 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)

编译器输出:

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并加载文件,它成功编译。为什么呢?

1 个答案:

答案 0 :(得分:6)

The Haskell Report restricts允许在类型类实例中显示的内容(默认情况下)

  

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

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

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

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

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}

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