需要灵活的实例?

我想为它的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 ...

当您需要由相同的构造函数执行的多个实例时,此方法可以很好地工作。

使用相等约束

打开GADTsTypeFamilies并写入

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 。 您可能可以使用新类型解决问题,但不值得麻烦。

链接地址: http://www.djcxy.com/p/33167.html

上一篇: Flexible instances needed?

下一篇: Automatic instance deriving after declaration