存在类型。为异构映射编写类的实例

时间:2012-10-26 14:01:35

标签: haskell existential-type

使用以下类型和类定义,我不明白为什么在下面创建instance时会出现错误。

我需要MyMap来保存异构值的地图。

{-# LANGUAGE ExistentialQuantification #-}
module Scratch.SO_ExtistentialTypes where

import Data.Map

type MyMap a = Map String a

class MyClass c where 
    getMyMap :: forall a. c -> MyMap a

data MyData = forall a. MyData {
    myMap ::  MyMap a
}

instance MyClass MyData where
    getMyMap = myMap -- <= ERROR

1 个答案:

答案 0 :(得分:9)

首先,这里的forall是多余的:

class MyClass c where 
    getMyMap :: forall a. c -> MyMap a

没有显式绑定的类型变量在最外层被普遍量化,因此这与c -> MyMap a完全相同。

除此之外,普遍量化的类型肯定不会与存在量化类型相匹配。 getMyMap的类型表示,如果类型为c,则会为类型MyMap a的任何可能选择生成类型a的值。另一方面,访问者myMap表示,如果类型为MyData,则会为某些特定但未知类型MyMap a生成类型a的值。

不可能让自己包含的展开存在类型(这需要exists对应于forall的量词),所以没有办法重写getMyMap这样的类型myMap是一个有效的实现。

对于具有存在类型的东西,你可以做的就是将它包装回另一种隐藏存在量词的数据类型,或者将它赋予一个具有普遍量化类型的参数的函数。例如,您可以在列表length上使用[a]a为存在类型。

在您的情况下,Map的值具有存在类型,没有其他结构或约束,因此它们几乎没用,也可能是()