输入私人类型的签名
好的,所以这里是一个不太明显的语言角落:
Haskell允许你导出一个类型签名的标识符,提到一个不导出的类型。 这到底是什么语义?
例如,假设我有
module Foobar (bar) where
data Foo = ...
bar :: String -> Foo
Foo
不会导出,而bar
是。 不过, bar
的类型提到了Foo
。 许多编程语言不会让你这样做,但Haskell会这样做。
所以现在怎么办? 看来我可以打电话给bar
,但结果却不能做得太多。 特别是,我(大概)不能说出结果类型的名称,这有点奇怪。 假设模块导出了一些以Foo
作为输入的函数,我应该能够以我的结果作为输入来调用这些函数......但是我不能在类型签名中这么说。
当然,做上面的事情不是一个好主意, 我不打算在实际的代码中这样做。 我只是好奇它究竟做了什么。
如果Haskell禁止你输出你自己的Foo
s类型的话,这可能会更有趣 - 这会让这里的情况更像存储型输入,这对于模块系统来说是一个好主意。
相反,类型信息泄漏。 实例信息也是如此。 对于“实例”,以下是不安全的
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。 如果您想强调使用某个类型而不允许用户构造它,请导出该类型。
链接地址: http://www.djcxy.com/p/20195.html上一篇: Type signature with private type
下一篇: How to use SemanticModel to check if variable has been tested?