私有类型的类型签名

7

好的,这里是语言中一个比较特殊的角落:

Haskell允许你导出一个标识符,其类型签名提到了一个没有被导出的类型。这到底意味着什么呢?

举个例子,假设我有以下代码:

module Foobar (bar) where

data Foo = ...

bar :: String -> Foo

Foo没有被导出,而bar被导出。虽然bar的类型提到了Foo,但许多编程语言不允许您这样做,但Haskell可以。

那现在怎么办?看起来我可以调用bar,但是不能对其结果进行太多操作。特别是,我(可能)不能说出结果类型的名称,这有点奇怪。假设如果该模块导出了一些以Foo作为输入的函数,则我应该能够使用我的结果作为输入调用这些函数...但整个过程中我无法在类型签名中表达出来。

当然,像上面这样做并不是一个好主意;我并不建议在实际代码中这样做。我只是好奇它实际上是做什么的。


2
就我所见,您已经正确分析了情况。您可以调用其他使用 Foo 的函数,也可以调用多态函数,但是您不能编写包含未导出名称的类型签名。 - kosmikus
1个回答

3

如果Haskell禁止您导出自己推断的Foo类型,那么这将使此处的情况更像存在类型,这对于模块系统来说是个好主意,可能更有趣。

相反,类型信息泄漏了。实例信息也是如此。对于“instance”,以下内容是不安全的。

module Foo ( foo ) where

  data Foo ...
    deriving (Data, Typeable) -- for internal use

  foo :: Foo -> IO ()

使用foo会允许“恶意”用户将Data.Data.fromConstr ...Foo统一起来,即使用户不应该能够生成Foo值。

-- mkFoo :: Constr -> Foo       (except I have to let this be inferred)
mkFoo c = out where
  out     = fromConstr c
  ignored = foo out

最终,我认为这是一个糟糕的API。如果你想强调类型的使用而不允许用户构造它,那么请导出该类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接