一般来说,答案是“不”。运行时表示实际上取决于确切的类型。
对于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"]
如果此拉取请求被接受,您的程序将被破坏。
最后,我还可以告诉您,Elm、Haskell 和 Idris 都不会展示您所追求的财产。运行时类型信息在 ML 世界中通常不是很重要的东西。有人可以说它在 Idris 中以某种方式有效地存在,但不是您所期望的方式。
您可能想尝试F#/Fable:它在这方面稍微强一些,但仍不如其原生 .NET 运行时。我不认为你可以突然从 JS 中检查 F# 对象的类型,但我知道 Fable 确实支持从 F# 本身访问 RTTI(以额外的性能成本),所以你至少可以制作函数来做到这一点和将它们导出到 JS。
如果您可以详细说明您的实际问题是什么,那么也许我(或其他人)可以提出替代解决方案。