haskell - 为什么我不能使 String 成为类型类的实例?

标签 haskell ghc typeclass type-systems

给定:

data Foo =
  FooString String
  …

class Fooable a where --(is this a good way to name this?)
  toFoo :: a -> Foo

我想让 String 成为 Fooable 的实例:

instance Fooable String where
  toFoo = FooString

GHC 然后提示:

Illegal instance declaration for `Fooable String'
    (All instance types must be of the form (T t1 ... tn)
     where T is not a synonym.
     Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Fooable String'

如果我使用[Char]:

instance Fooable [Char] where
  toFoo = FooString

GHC 提示:

Illegal instance declaration for `Fooable [Char]'
   (All instance types must be of the form (T a1 ... an)
    where a1 ... an are 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 `Fooable [Char]'

问题:

  • 为什么我不能创建 String 和类型类的实例?
  • 如果我添加一个额外的标志,GHC 似乎愿意让我逃脱惩罚。这是个好主意吗?

最佳答案

这是因为String只是[Char]的类型别名,它只是类型构造函数[]的应用Char 类型,因此其形式为 ([] Char)。它不是 (T a1 .. an) 形式,因为 Char 不是类型变量。

此限制的原因是为了防止实例重叠。例如,假设您有一个实例 Fooable [Char],后来有人定义了一个实例 Fooable [a]。现在编译器将无法确定您想要使用哪一个,并且会给您一个错误。

通过使用 -XFlexibleInstances,您基本上向编译器 promise 您不会定义任何此类实例。

根据您想要完成的任务,定义一个包装器可能会更好:

newtype Wrapper = Wrapper String
instance Fooable Wrapper where
    ...

关于haskell - 为什么我不能使 String 成为类型类的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5941701/

相关文章:

Haskell 处理字符列表

haskell - Cabal:阻止安装基础包

haskell - Haskell 中的延续与调用堆栈

haskell - 如何进一步约束 Haskell 中的现有类型类

haskell - haskell中的递归实例

haskell - 可重置累加器行为?

haskell - haskell中给定种子的随机数质量

haskell - 将字符串映射到 Haskell 中的数据类型

haskell - 定义泛型实例时触发单态限制

Haskell 除数