给定:
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/