2012-10-26 29 views
1

使用以下类型和类定义,我不明白为什么我会在下面创建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 
+2

你想在这里完成什么?因为我严重怀疑这是一个好方法。 –

+0

@ C.A.McCann'type'和'class'是定义'API'的模块的一部分。 'data'和'type'是(简化的)暂定实现。 –

+0

@ C.A.McCann另一种说法是:如何创建一个可以作为MyClass实例的数据类型(MyData)? –

回答

9

一方面,这里的forall是多余的:

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

没有明确的绑定类型变量在最外层是普遍定量,所以这是完全一样,只是c -> MyMap a

除此之外,普遍量化的类型当然不会匹配存在量化类型。 getMyMap的类型表示,如果类型为c,则对于a类型的任何可能的选择,它将生成MyMap a类型的值。另一方面,访问者myMap说,给定值为MyData的值时,它将产生MyMap a类型的值,用于某些特定但未知的类型a

这是不可能有解开生存类型的漂浮本身(这需要对应forallexists量词),所以没有办法改写的getMyMap,使得myMap是一种有效的实现类型。

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

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

+0

非常感谢。我现在明白'getMyMap'类型的定义表达了错误的东西(它返回一个* universally *量化类型的Map)。那么,如何在一个类中表达我需要一个函数来返回一个异构值的Map(如果可能的话)? –

+1

@BGR:表达这种类型是一回事,但更大的问题实际上是使用包含异构类型值的结构。使用这种类型的奥术技术确实存在(哈,哈),但我的经验法则是“如果你需要问怎么做,不要”。如果你想要一个理智的API,这不是一个可怕的痛苦,你可能需要一个不同的设计。 –

+0

:)足够公平。感谢您花时间。 –