将PureScript类型暴露给JavaScript

时间:2019-12-26 22:45:50

标签: haskell purescript

我可以在JS中使用PureScript类型吗?例如:

type SomeType = /*type declaration*/

func :: SomeType
func = /*type construction*/

然后在JS中执行以下操作:

let a = module.func()
a instanceof module.SomeType === true

如果没有,我可以使用任何一种Haskellish语言(Elm,GHCJS,Idris吗?)?

1 个答案:

答案 0 :(得分:5)

通常,答案为“否”。运行时表示形式实际上取决于确切的类型。

对于data声明,每个构造函数都将由一个JS“类”表示,如下所示:

-- PureScript:
data T = A Int | B

x :: T
x = A 42

// JS:
function A(value0) { this.value0 = value0; }
A.create = function(value0) { return new A(value0); }

function B() { }
B.value = new B();

var x = A.create(42);

因此,从技术上讲,您可以使用instanceof来区分大小写,但不能确定类型本身。

另一方面,对于newtype,类型包装器将被完全擦除,因为这就是newtype的重点:

-- PureScript:
newtype T = T Int

x :: T
x = T 42

// JS:
var x = 42;

对于类型同义词(用type关键字声明),没有明显的表示形式。也就是说,此类类型在运行时的表示方式与其右侧表示相同:

-- PureScript
type T = Int

x :: T
x = 42

// JS:
var x = 42;

这也适用于裸记录,因为它们也只是类型同义词:

-- PureScript
type R = { x :: Int, y :: String }

r :: R
r = { x: 42, y: "foo" }

// JS:
var r = { x: 42, y: "foo" }

因此,最重要的是:没有很好的方法来做到这一点。 PureScript根本不对运行时表示作出任何保证。它对程序行为做出了很好的承诺,但对在JS(或您正巧使用的任何其他后端)中如何实现它却无能为力。

这是另一个问题:,因为PureScript不会做出任何这样的承诺,所以依靠您(我的)对当前实现的知识是一个非常糟糕的主意,因为下一版本的编译器可能会完全更改它。 PureScript可以做到这一点,因为它没有承诺。看看它如何工作?

例如,我知道管道中的某个拉取请求会将data表示形式切换为数组,例如:

-- PureScript:
data T = A Int | B

x, y :: T
x = A 42
y = B

// JS:
var x = ["A", 42]
var y = ["B"]

如果此拉取请求曾被接受,则您的程序将被破坏。


最后,我还可以告诉您,埃尔姆,哈斯克尔和伊德里斯都不会展示您所追求的财产。在ML Universe中,运行时类型信息通常不是很重要的事情。有人可以说它以某种方式有效地存在于Idris中,但并非您所期望的那样。

您可能要尝试F#/Fable:在这方面它要强一些,但仍然不如其本机.NET运行时好。我不认为您可以从JS中突然检查F#对象的类型,但是我知道Fable确实支持从F#本身访问RTTI(以额外的性能成本),因此您至少可以使函数做到这一点,并且将它们导出到JS。

如果您可以扩大实际问题的范围,那么也许我(或其他人)可以提出替代解决方案。