【问题标题】:Type signature with private type具有私有类型的类型签名
【发布时间】:2014-05-03 21:02:33
【问题描述】:

好的,这里是语言的一个不起眼的角落:

Haskell 允许您导出一个标识符,该标识符的类型签名提到了一个导出的类型。这到底是什么语义?

例如,假设我有

module Foobar (bar) where

data Foo = ...

bar :: String -> Foo

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

那么现在呢?看来我可以打电话给bar,但它的结果却无能为力。特别是,我(大概)不能说出结果类型的名称,这有点奇怪。据推测,如果模块导出了一些以Foo 作为输入的函数,我应该能够以我的结果作为输入来调用这些函数......但是我不能在类型签名中这么说。

当然,执行上述操作并不是一个好主意;我不建议在实际代码中这样做。我只是好奇它实际上做了什么

【问题讨论】:

  • 据我所知,您对情况的分析是正确的。您可以使用Foo 调用其他函数,也可以调用多态函数,但不能编写提及未导出名称的类型签名。

标签: haskell types


【解决方案1】:

如果 Haskell 禁止你导出你自己的类型并推断出Foos 可能会更有趣——这会使这里的情况更像是存在类型,这对于模块系统来说是一个好主意.

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

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。如果您想强调类型的使用而不允许用户构造它,请导出该类型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-31
    • 1970-01-01
    • 1970-01-01
    • 2012-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-12
    相关资源
    最近更新 更多