繁体   English   中英

GHC是否使用存在类型的动态调度?

[英]Does GHC use dynamic dispatch with existential types?

下面的代码是否使用动态分派,因为它在C ++或Java中被理解?

据我所知,在最后一行,编译器不可能在编译时知道调用(==)的实现,但代码编译并产生正确的结果。 有人可以解释一下,这背后有什么样的实现(比如vptr)?

{-# LANGUAGE ExistentialQuantification #-}

data Value = A Int

data ForallFunc = forall a. Eq a => Forall (Value -> a) 

unpackA (A int) = int

equalityTest :: Value -> Value -> ForallFunc -> Bool            
equalityTest arg1 arg2 (Forall unpacker) =
  let a1 = unpacker arg1
      a2 = unpacker arg2 in
    a1 == a2

粗略地说,是的。

当你使用有存在量化时,即当量化类型变量受某些约束C a => ...限制时,GHC将在构造函数中存储一些指针,记住C a的方法,使它们可以稍后访问,当您在该构造函数上进行模式匹配时。

通常使用单个指针,非常类似于许多OOP实现中的vtablevptr 编译器也可以直接存储指向方法的指针,避免间接。 我认为这是由GHC完成的,因为类型类中只有一个方法。 它也可以在极少数(比方说两种)方法时使用 - 这会使每个值的内存占用更大,但访问速度更快。

因此,编译代码是完美的,好像约束被Eq字典替换,列出了它的方法。 那是:

data EqDict a = EqDict
   { eq  :: a->a->Bool
   , new :: a->a->Bool }

data ForallFunc = forall a. Forall EqDict (Value -> a) 

unpackA (A int) = int

equalityTest :: Value -> Value -> ForallFunc -> Bool            
equalityTest arg1 arg2 (Forall eqDict unpacker) =
  let a1 = unpacker arg1
      a2 = unpacker arg2 in
    eq eqDict a1 a2

当然,编译构造函数调用Forall someFunction大致是通过为其特定类型提供所需的==/=函数的实现来编译的,这些函数将通过存在量化来抽象出来。

是的,ghc使用一种动态调度形式。 Eq a约束意味着ForallFunc的表示将包含在运行时用于调用正确的相等函数的字典(对应于vtable)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM