需要灵活的实例?
我想为它的C表示写一个Haskell类型的Convertible实例
它看起来像这样:
instance Convertible Variable (IO (Ptr ())) where
现在GHC抱怨说:
Illegal instance declaration for `Convertible
Variable (IO (Ptr ()))'
(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 `Convertible Variable (IO (Ptr ()))'
如果你的实例声明中有空闲类型,我认为需要灵活实例,但事实并非如此。 添加正确的编译指示时,我可以编译它,但任何人都可以解释为什么我需要这个?
是的,你需要灵活的实例。 没有它,你所有的类型实例都必须看起来像
instance Foo (Maybe a) where
instance Foo (IO a) where
instance Foo (Either a b) where
如果你想要做的比其他任何事情TypeConstructor a1 a2 a3 ...
(和a
■找是类型变量),比您需要灵活的实例。 但它是最常用的语言扩展之一,不要使用它。
在这种情况下,您通常可以避免使用FlexibleInstances
。 有两种一般方法:
使用辅助类
instance ConvIO a => Convertible Variable (IO a) where
method = methodIO
class ConvIO p where
methodIO :: ...
-- similar to the signature for the Convertible method,
-- but with Variable and IO baked in
instance ConvIOPtr u => ConvIO (Ptr u) where
methodIO = methodIOPtr
class ConvIOPtr u where
methodIOPtr :: ...
instance ConvIOPtr () where ...
当您需要由相同的构造函数执行的多个实例时,此方法可以很好地工作。
使用相等约束
打开GADTs
或TypeFamilies
并写入
instance a ~ Ptr () => Convertible Variable (IO a) where ...
这种方法对类型推断有帮助,但只有当你只需要一个以IO
为首的实例时才有意义。
你可以混合搭配
您可以使用辅助类来通过IO
,然后使用相等约束来通过Ptr
。
instance u ~ () => ConvIO (Ptr u) where ...
或者你可以使用一个相等约束来通过IO
和一个辅助类来通过Ptr
:
instance (a ~ Ptr u, ConvIOPtr u) => Convertible Variable (IO a)
这些不起作用
如果你需要一个参数是一个类型变量的实例,那么你真的无法避免使用FlexibleInstances
。 您可能可以使用新类型解决问题,但不值得麻烦。