【问题标题】:Haskell unsafeCoerce newtype to identical newtypeHaskell unsafeCoerce newtype 到相同的 newtype
【发布时间】:2012-02-20 15:24:46
【问题描述】:

假设有一个新类型声明:

newtype T = T Int

此声明在模块中但未导出。我想将 T 类型的值传递给函数。现在,我可以使用完全相同的定义声明我自己的 T 版本。如果我将(my.T 0) 传递给期望(hidden.T 0) 的函数,编译器当然会抱怨。我将使用 unsafeCoerce 将前者强制为后者。提到here,“在新类型和它包装的类型之间”使用是安全的。我想检查一下在我描述的情况下它是否也安全。

我知道这是不赞成和反对良好软件实践、类型理论、函数式编程哲学、ghc 政策、常识等的所有原则的。然而,我想知道这是否会“正常”工作。

【问题讨论】:

  • 你为什么要这样做?
  • 仅供参考,unsafeCoerce 比传统语言中的全局变量更邪恶。它的使用通常保留在问题无法以任何其他方式解决的情况下——例如当类型系统不足以表达一些不变量等时。这种情况,AFAICT,不是其中之一。 (除非T 构造函数没有被导出,所以你不应该知道T 等价于Int,但你需要知道)
  • @luqui 感谢您的提醒!
  • @augustss 因为包的作者没有参加,因为他的类型是可见的,但我真的需要它。
  • @aelguindy。然后换个包。

标签: haskell types type-conversion


【解决方案1】:

这对于当前的 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

最后,您可以根据需要导出 opaque 类型。例如:

module Foo (T) where

import Foo.Types (T(..))

makeT :: Int -> T
makeT = T

可以使用强制转换,但依赖它是个坏主意。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-18
    • 2010-09-05
    • 2022-10-12
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 2015-07-21
    • 2014-10-25
    相关资源
    最近更新 更多