首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型类和多态多态

类型类和多态多态
EN

Stack Overflow用户
提问于 2020-02-21 08:21:54
回答 1查看 126关注 0票数 3

假设我有一个可以取消装箱/重新装箱的值的类:

代码语言:javascript
复制
class Unboxable a (rep :: RuntimeRep) (unboxedTy :: TYPE rep) | a -> rep, a -> unboxedTy where
  unbox :: a -> unboxedTy
  rebox :: unboxedTy -> a

像这样的实例是非常好的:

代码语言:javascript
复制
instance Unboxable Int 'IntRep Int# where
  unbox (I# w) = w
  rebox = I#

但是如果我尝试支持不可装箱的值的元组,比如

代码语言:javascript
复制
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# )

我得到了一个超出我理解的错误:

代码语言:javascript
复制
    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上。

这到底是什么意思,有没有一种方法来表达最后一个实例?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-21 09:42:27

不能包含具有未知RuntimeRep的变量。这种情况是不可能的。例如,(Float, Float)的实例必须存储/加载32位的值,但(Double, Double)的实例将处理64位的值。但是,这样的实例必须是这个实例的专门化,从而共享代码,这使得这种区别是不可能的。为了捕捉到这一点,当引入一个变量时,它的类型将与TYPE rep匹配,如果rep不是完全已知的(本质上就是需要传递该值的“调用约定”),那么就会引发您所看到的错误。“多态多态”这个短语有点老旧,“多态”指的是提升类型(通过包含底值定义,所有类型都是装箱的(例如Int[String]))和未提升类型(没有底值,其中一些是装箱的(ByteArray#),一些是拆箱的(Int#))之间的区别。如果你真的想要,你可以使用模板Haskell来生成这些装箱和拆箱函数,但你不能获得所有这些函数(因为有无限多的类型,你不能使用多态性)。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60330481

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档