我可以在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?)?
对于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。
如果您可以扩大实际问题的范围,那么也许我(或其他人)可以提出替代解决方案。