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

hug*_*omg 1 haskell existential-type

在下面的代码中,我所做的所有返回值foo都是使用它的Show接口

foo :: String
foo = "asdf"

main = do
    print foo
Run Code Online (Sandbox Code Playgroud)

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


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

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

sha*_*haf 7

对于存在类型来说确实是可能的,但这可能是一个坏主意.

你存在类型的方式ConnWrapper就像你说的那样:

data ConnWrapper = forall conn. IConnection conn => ConnWrapper conn
Run Code Online (Sandbox Code Playgroud)

这种类型相对简单:它是一个IConnection字典以及与之兼容的类型的值.如果x :: conn,并且conn是一个实例IConnection,那么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可能会以这种方式使用,但......