新类型与外国进口数据

newtype vs foreign import data

选择这些选项的实际原因是什么?

例如:

  1. foreign import data Foo :: Type -> Type
  2. newtype Foo a = Foo a

让我们假设在这两种情况下,我们通过一些函数得到一个 Foo:

foreign import newFoo :: forall a. a -> Foo a

区别在于 newtype 的数据表示是已知的,而 foreign import 则不是。

这样做的一个结果是,使用 newtype,您可以通过模式匹配从 Foo a 中得到 a

let foo = newFoo 42
let (Foo fourtyTwo) = foo

并且 foreign import 你不能那样做。

另一个结果是 foreign import 函数 newFoo 可以自由选择表示,它不一定要等同于 a,例如:

// JavaScript
exports.newFoo = function (a) { return { wrapped: a } }

但是 newtype 必须正好是 a:

// JavaScript
exports.newFoo = function (a) { return a }

然后还有自动推导Newtypeclass的便利,这开启了一些自动化的可能性。


回复评论中的第二个问题(以后请post单独提问):

如果您的 Foo 没有类型参数,但定义如下:

// Case 1
data Foo = Foo

// Case 2
foreign import data Foo :: Type
foreign import newFoo :: Foo

此处的区别与上面相同:对于 data 表示是已知的,对于 foreign import 则不是。

它在实践中的表现方式实际上取决于您的背景。我能想到的一个例子是 EqShowGeneric 等的自动推导,对于 foreign import 方法需要手动编码。想到的另一个例子是 data Foo 静态保证只有一个值,而 newFoo 可以在每次调用中自由 return 不同的值。