是否有可能只暴露返回值的类型类接口?

时间:2013-06-11 00:48:53

标签: haskell existential-type

在以下代码中,我对foo的返回值所做的一切都是使用其Show接口

foo :: String
foo = "asdf"

main = do
    print foo

有没有办法修改foo的类型签名来强制执行此操作,禁止人们将字符串视为字符列表,只允许他们通过抽象类型类接口访问它?我认为对于存在类型可能是可能的,但我不知道如何。


我想这样做的原因是因为在HDBC数据库库中,所有功能都可用作IConnection类型类的方法。我正在编写创建数据库连接的函数,我想知道是否可能使其返回类型反映抽象接口,而不是返回具体的Sqlite3 Connection

现在我搜索了一下,我发现有一个ConnWrapper数据类型可用,但我仍然无法理解这一切是如何组合在一起的。返回ConnWrapper是唯一的出路吗?

1 个答案:

答案 0 :(得分:7)

对于存在类型确实可能,但它很可能是bad idea

使用存在类型的方式是ConnWrapper,就像你说的那样:

data ConnWrapper = forall conn. IConnection conn => ConnWrapper conn

这种类型相对简单:它是一个IConnection字典以及与之兼容的类型的值。如果x :: connconnIConnection的实例,那么ConnWrapper x :: ConnWrapper。给定y :: ConnWrapper,除了它是IConnection的实例之外,你对它的值的类型一无所知。所以你可以说case y of ConnWrapper z -> disconnect z,但你不能说case y of ConnWrapper z -> z - 你不能给它任何Haskell类型。

ConnWrapper也是IConnection的直接实例,由于该类非常简单,这意味着您几乎不需要直接在ConnWrapper上进行模式匹配。您可以只需使用disconnect y等等。)

如果您正在制作API,我强烈建议您重新考虑我上面链接的帖子,或至少理解这种方法。在Haskell中使用ExistentialTypes实际上比非存在方法更复杂。例如,您应该看到为什么data Foo = forall a. Show a => Foo a(几乎)等同于String。看起来HDBC可能会以这种方式使用,但是......