Joh*_*ler 84 haskell type-systems typeclass ghc
鉴于:
data Foo =
FooString String
…
class Fooable a where --(is this a good way to name this?)
toFoo :: a -> Foo
Run Code Online (Sandbox Code Playgroud)
我想做String一个实例Fooable:
instance Fooable String where
toFoo = FooString
Run Code Online (Sandbox Code Playgroud)
然后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'
Run Code Online (Sandbox Code Playgroud)
如果相反我使用[Char]:
instance Fooable [Char] where
toFoo = FooString
Run Code Online (Sandbox Code Playgroud)
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]'
Run Code Online (Sandbox Code Playgroud)
问题:
ham*_*mar 64
这是因为String它只是一个类型别名[Char],它只是类型构造函数[]在类型上的应用Char,所以这就是形式([] Char).这不是形式,(T a1 .. an)因为Char它不是一个类型变量.
这种限制的原因是为了防止重叠的实例.例如,假设你有一个instance Fooable [Char],然后有人后来出现并定义了一个instance Fooable [a].现在编译器将无法确定您想要使用哪一个,并且会给您一个错误.
通过使用-XFlexibleInstances,您基本上向编译器承诺,您将不会定义任何此类实例.
根据您要完成的任务,定义包装器可能更好:
newtype Wrapper = Wrapper String
instance Fooable Wrapper where
...
Run Code Online (Sandbox Code Playgroud)
Don*_*art 18
您遇到了经典Haskell98类型类的两个限制:
两个语言扩展提升了这些繁重的限制:
-XTypeSynonymInstances它允许你使用类型synoyms(比如Stringfor [Char]),和:
-XFlexibleInstances这解除了对T a b ..参数是类型变量的形式的实例类型的限制.该-XFlexibleInstances标志允许实例声明的头部提及任意嵌套类型.
请注意,解除这些限制有时会导致重叠的实例,此时,可能需要额外的语言扩展来解决歧义,允许GHC为您选择一个实例.
参考文献:
在大多数情况下,FlexibleInstances 并不是一个好的答案。更好的替代方案是将 String 包装在新类型中或引入一个辅助类,如下所示:
class Element a where
listToFoo :: [a] -> Foo
instance Element Char where
listToFoo = FooString
instance Element a => Fooable [a] where
toFoo = listToFoo
Run Code Online (Sandbox Code Playgroud)
另请参阅: http: //www.haskell.org/haskellwiki/List_instance