键入私人类型的签名

时间:2014-05-03 11:57:04

标签: haskell types

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

Haskell允许您导出标识符,该标识符的类型签名提到 not 导出的类型。究竟是什么语义?

例如,假设我有

module Foobar (bar) where

data Foo = ...

bar :: String -> Foo

Foo未导出,bar为。{1}}。但bar类型提及Foo。许多编程语言都不允许你这样做,但是Haskell确实如此。

那么现在呢?似乎我可以拨打bar,但是不能对其结果做多少。特别是,我(大概)不能说出结果类型的名称,这有点奇怪。假设模块导出了一些以Foo为输入的函数,我应该能够将那些以我的结果作为输入的函数调用...但是我不能在类型签名中这样说。

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

1 个答案:

答案 0 :(得分:3)

如果Haskell禁止你导出你自己的推断Foo的类型,这可能会更有趣 - 这会使这里的情况更像是存在性打字,这是一个好主意模块系统。

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

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