解析存在类型中的函数调用

Sil*_*olo 6 haskell types existential-type

在Haskell的existentials上阅读本页后,我不得不测试这种行为的限制,所以我编写了以下代码片段:

{-# LANGUAGE ExistentialQuantification #-}

data Showable = forall a. Show a => MkShowable a

pack :: Show a => a -> Showable
pack = MkShowable

instance Show Showable where
    show (MkShowable x) = show x
Run Code Online (Sandbox Code Playgroud)

Showable类型ShowBox与上述链接中创建的类型非常相似.然后我创建了这个人为的例子来说明我的问题.

showSomething :: Bool -> Showable
showSomething True = pack 1
showSomething False = pack "ABC"

main :: IO ()
main = do
  x <- getLine
  let y = read x
  print $ showSomething y
Run Code Online (Sandbox Code Playgroud)

这段代码(工作正常)要求用户输入(应为'True'或'False'),然后打印输出1是否为True或"ABC"是否为False.

但我没能完全理解系统是如何做到这一点的.从数学上讲,它非常有意义.但我不知道计算机是如何解决它的.对我来说,它看起来像系统使得在关于是否调用运行时决定Intshow实例或Stringshow功能,但是这将意味着一个像C++的虚函数表,我不相信Haskell有一个概念存在.

我的问题是:它如何解决这个问题?系统无法预先知道我是要输入true还是false,因此它无法知道show在编译时调用哪个,但它在两种情况下都清楚有效.

Pet*_*lák 6

实现类型类的一种方法是传递一个实现类型类的函数字典.例如带签名的函数

f :: Show a => T
Run Code Online (Sandbox Code Playgroud)

将被翻译成

f' :: (a -> String) -> T
Run Code Online (Sandbox Code Playgroud)

由编译器和show内部使用的时候f,它被附加参数替换(实际上会有更多的函数,所有声明的函数Show).

同样是数据类型

forall a . Show a => MkShowable a
Run Code Online (Sandbox Code Playgroud)

将被翻译成

forall a . MkShowable' (a -> String) a
Run Code Online (Sandbox Code Playgroud)

所以转换后的代码可能如下所示:

{-# LANGUAGE ExistentialQuantification #-}

data Showable' = forall a . MkShowable' (a -> String) a

pack' :: Show a => a -> Showable'
pack' = MkShowable' show

instance Show Showable' where
    show (MkShowable' f x) = f x

showSomething :: Bool -> Showable'
showSomething True = pack' 1
showSomething False = pack' "ABC"
Run Code Online (Sandbox Code Playgroud)

pack被调用时,show实现传递给构造以及以便在需要时,它的可用.