假设有一个新类型声明:
newtype T = T Int
此声明位于模块中但未导出。我想将 T 类型的值传递给函数。现在,我可以使用完全相同的定义来声明我自己的 T 版本。如果我将 (my.T 0)
传递给需要 (hidden.T 0)
的函数,编译器当然会提示。我将使用 unsafeCoerce 将前者强制为后者。提到了here这种用法“在新类型和它所包装的类型之间”是安全的。我想检查一下在我描述的情况下它是否也安全。
我知道这不符合良好软件实践、类型理论、函数式编程哲学、ghc 政策、常识等的所有原则。然而,我想知道这是否会“正常”工作。
最佳答案
这对于当前的 GHC 实现来说可能是安全的,但这不是解决您的特定问题的推荐方法。
通常使用的模式是有一个像这样的内部模块:
module Foo.Types (T(..)) where
newtype T = T Int
该模块在您的 Cabal 文件中被声明为未导出。然后,在要使用该类型的模块中,导入 Types
模块,并直接使用构造函数:
module Foo.Bla where
import Foo.Types (T(..))
f :: T -> Bla
f (T int) = makeBla int
最后,您可以根据需要导出不透明类型。例如:
module Foo (T) where
import Foo.Types (T(..))
makeT :: Int -> T
makeT = T
可以使用强制来代替,但依赖它不是一个好主意。
关于Haskell unsafe将新类型强制转换为相同的新类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9036682/