假设我有一个可以取消装箱/重新装箱的值的类:
class Unboxable a (rep :: RuntimeRep) (unboxedTy :: TYPE rep) | a -> rep, a -> unboxedTy where
unbox :: a -> unboxedTy
rebox :: unboxedTy -> a像这样的实例是非常好的:
instance Unboxable Int 'IntRep Int# where
unbox (I# w) = w
rebox = I#但是如果我尝试支持不可装箱的值的元组,比如
instance (Unboxable a repa unboxedTyA, Unboxable b repb unboxedTyB)
=> Unboxable (a, b) ('TupleRep '[ repa, repb ]) (# unboxedTyA, unboxedTyB #) where
unbox (a, b) = (# unbox a, unbox b #)
rebox (# a# , b# #) = ( rebox a# , rebox b# )我得到了一个超出我理解的错误:
A levity-polymorphic type is not allowed here:
Type: unboxedTyA
Kind: TYPE repa
In the type of binder ‘a#’
|
32 | rebox (# a# , b# #) = ( rebox a# , rebox b# )
| ^^如果rebox被注释掉,unbox也会出现类似的错误。如果这很重要,我在ghc 8.8.2上。
这到底是什么意思,有没有一种方法来表达最后一个实例?
发布于 2020-02-21 09:42:27
不能包含具有未知RuntimeRep的变量。这种情况是不可能的。例如,(Float, Float)的实例必须存储/加载32位的值,但(Double, Double)的实例将处理64位的值。但是,这样的实例必须是这个实例的专门化,从而共享代码,这使得这种区别是不可能的。为了捕捉到这一点,当引入一个变量时,它的类型将与TYPE rep匹配,如果rep不是完全已知的(本质上就是需要传递该值的“调用约定”),那么就会引发您所看到的错误。“多态多态”这个短语有点老旧,“多态”指的是提升类型(通过包含底值定义,所有类型都是装箱的(例如Int,[String]))和未提升类型(没有底值,其中一些是装箱的(ByteArray#),一些是拆箱的(Int#))之间的区别。如果你真的想要,你可以使用模板Haskell来生成这些装箱和拆箱函数,但你不能获得所有这些函数(因为有无限多的类型,你不能使用多态性)。
https://stackoverflow.com/questions/60330481
复制相似问题