您要找的是“存在类型 https://wiki.haskell.org/Existential_type”,而 PureScript 只是不支持像 Haskell 那样的语法级别的那些。但是你可以推出自己的:-)
一种方法要走是“数据抽象” - 即根据您想要对其执行的操作对数据进行编码。例如,假设您想要获取以下值x
在某个时刻脱离他们。在这种情况下,创建一个数组:
type RecordRep = Unit -> Int
toRecordRep :: forall r. { x :: Int | r } -> RecordRep
toRecordRep {x} _ = x
-- Construct the array using `toRecordRep`
test :: Array RecordRep
test = [ toRecordRep {x:1}, toRecordRep {x:1, y:1} ]
-- Later use the operation
allTheXs :: Array Int
allTheXs = test <#> \r -> r unit
如果您有多个此类操作,您可以随时记录它们:
type RecordRep =
{ getX :: Unit -> Int
, show :: Unit -> String
, toJavaScript :: Unit -> Foreign.Object
}
toRecordRep r =
{ getX: const r.x
, show: const $ show r.x
, toJavaScript: const $ unsafeCoerce r
}
(注意Unit
每个函数中的参数 - 它们是为了懒惰而存在的,假设每个操作都可能很昂贵)
但如果你真的需要类型机械,你可以做我所说的“穷人的存在主义类型”。如果仔细观察,存在类型只不过是“延迟”类型检查 - 延迟到您需要查看类型的程度。在 ML 语言中推迟某些事情的机制是什么?没错——一个函数! :-)
newtype RecordRep = RecordRep (forall a. (forall r. {x::Int|r} -> a) -> a)
toRecordRep :: forall r. {x::Int|r} -> RecordRep
toRecordRep r = RecordRep \f -> f r
test :: Array RecordRep
test = [toRecordRep {x:1}, toRecordRep {x:1, y:1}]
allTheXs = test <#> \(RecordRep r) -> r _.x
它的工作原理是这样的RecordRep
包装一个函数,该函数接受另一个函数,该函数是多态的r
- 也就是说,如果您正在查看RecordRep
,你必须准备好给它一个可以与任何r
. toRecordRep
以使其精确类型在外部不可见的方式包装记录,但它将用于实例化您最终将提供的通用函数。在我的例子中这样的函数是_.x
.
但请注意,这里存在问题:行r
当您开始使用数组的元素时,它实际上是未知的,因此您无法对其执行任何操作。就像,完全一样。你所能做的就是得到x
字段,因为它的存在是硬编码在签名中的,但除了x
-你只是不知道。这是设计使然:如果你想把anything进入数组,你必须准备好得到anything出来了。
现在,如果您确实想对这些值执行某些操作,则必须通过约束来解释这一点r
, 例如:
newtype RecordRep = RecordRep (forall a. (forall r. Show {x::Int|r} => {x::Int|r} -> a) -> a)
toRecordRep :: forall r. Show {x::Int|r} => {x::Int|r} -> RecordRep
toRecordRep r = RecordRep \f -> f r
test :: Array RecordRep
test = [toRecordRep {x:1}, toRecordRep {x:1, y:1}]
showAll = test <#> \(RecordRep r) -> r show
通过show
像这样的函数是有效的,因为我们已经约束了行r
以这样的方式Show {x::Int|r}
必须存在,因此,应用show
to {x::Int|r}
必须工作。根据需要对您自己的类型类重复此操作。
这是有趣的部分:由于类型类是作为函数字典实现的,因此上面描述的两个选项实际上是等效的 - 在这两种情况下,您最终都会传递函数字典,只有在第一种情况下它是显式的,但在第二种情况下编译器会这样做为你。
顺便说一句,这也是 Haskell 语言支持的工作原理。