我想将Haskell类型的Convertible实例写入其C表示
它看起来像这样:
instance Convertible Variable (IO (Ptr ())) where
Run Code Online (Sandbox Code Playgroud)
现在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 ()))'
Run Code Online (Sandbox Code Playgroud)
如果你的实例声明中有自由类型,我认为需要灵活实例,但事实并非如此.我可以在添加正确的pragma时进行编译,但有人可以解释为什么我需要这个吗?
Dan*_*zer 14
是的,你需要灵活的实例.没有它,你的所有类型类实例都必须看起来像
instance Foo (Maybe a) where
instance Foo (IO a) where
instance Foo (Either a b) where
Run Code Online (Sandbox Code Playgroud)
如果你想做除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 ...
Run Code Online (Sandbox Code Playgroud)
当您需要由同一构造函数领导的多个实例时,此方法非常有效。
打开GADTs或TypeFamilies并写入
instance a ~ Ptr () => Convertible Variable (IO a) where ...
Run Code Online (Sandbox Code Playgroud)
这种方法往往对类型推断有很大帮助,但只有当您只需要一个以 开头的实例时才有意义IO。
您可以使用辅助类来遍历IO,然后使用等式约束来遍历Ptr。
instance u ~ () => ConvIO (Ptr u) where ...
Run Code Online (Sandbox Code Playgroud)
或者您可以使用等式约束来遍历IO并使用辅助类来遍历Ptr:
instance (a ~ Ptr u, ConvIOPtr u) => Convertible Variable (IO a)
Run Code Online (Sandbox Code Playgroud)
如果您需要一个其参数之一是类型变量的实例,那么您确实根本无法避免FlexibleInstances。您也许可以使用新类型来解决该问题,但不值得这么麻烦。
| 归档时间: |
|
| 查看次数: |
4164 次 |
| 最近记录: |