Does GHC use dynamic dispatch with existential types?

让人想犯罪 __ 提交于 2021-01-27 09:54:58

问题


Does the following bit of code use dynamic dispatch as it's understood in C++ or Java?

As I understand, at the last line, compiler cannot possibly know at compile time which implementation of (==) to call, yet the code compiles and produces correct results. Can someone please explain, what kind of implementation (vptr, for example) lies behind this?

{-# 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

回答1:


Roughly, yes.

When you use a bounded existential quantification, i.e. when the quantified type variable is restricted by some constraint C a => ... then GHC will store some pointer(s) inside the constructor, remembering the methods of C a so that they can be accessed later on, when you pattern match on that constructor.

Usually a single pointer is used, much like a vptr to a vtable in many OOP implementations. The compiler could also instead store the pointers to the methods directly, avoiding the indirection. I think this is done by GHC when there's only one method in the type class. It might also be used when there are very few, say two, methods -- this would make the memory footprint of each value larger, but faster to access.

So, compiling your code is rouhgly done as if the constraint is replaced with an Eq dictionary, listing its methods. That is:

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

Of course, compiling a constructor call Forall someFunction is compiled, roughly, by providing the implementation for the needed ==, /= functions, on their specific type which will be abstracted away by the existential quantification.




回答2:


Yes, ghc uses a form of dynamic dispatch. The Eq a constraint means that the representation for ForallFunc will contain a dictionary (corresponds to a vtable) which is used at runtime to call the right equality function.



来源:https://stackoverflow.com/questions/49963134/does-ghc-use-dynamic-dispatch-with-existential-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!