结合Purescript中的记录

时间:2016-03-14 10:59:58

标签: purescript

鉴于我在purescript中有以下记录:

let name = {name: "Jim"}
let age = {age: 37}

是否可以将这两个记录组合成一般的方式? 类似的东西:

name 'comb' age

这样我得到以下记录:

{name: "Jim", age: 37}

似乎有可能使用Eff rowtype,但我很好奇是否可以使用'normal'记录。我是purescript的新手,也是它的记录语法。

非常感谢。

2 个答案:

答案 0 :(得分:9)

编辑:

目前处理记录操作的官方包purescript-record seems - 您可以找到提供mergebuild功能的Builder.purs:< / p>

> import Data.Record.Builder (build, merge)
> name = {name: "Jim"}
> age = {age: 37}
> :t (build (merge age) name)
{ name :: String
, age :: Int
}

API注意:

乍一看这个API看起来过于复杂 - 特别是当你将它与简单的unionMerge name age调用进行比较时({1}}在本回答结尾处被引入)。 unionMerge存在(以及此API)背后的原因是性能。我可以向你保证:

Builder

只创建一条新记录。但是这个:

> build (merge name >>> merge age) {email: "someone@example.com"}

在执行期间创建两条记录。

更有趣的是如何实现> unionMerge name (unionMerge age {email: "someone@example.com"}) Builderbuild - merge是函数周围的新类型包装器(其组成只是一个函数组合)和Builder只是复制版本记录的函数应用程序:

build

newtype Builder a b = Builder (a -> b) build (Builder b) r1 = b (copyRecord r1) 中执行了merge

unsafeMerge

那么我们为什么要在这里获得任何东西?因为我们可以确定中间结果不能逃避功能范围,并且每个值在构建器链中只消耗一次。因此,我们可以在适当的位置执行所有转换&#34;以可变的方式。换句话说,这个merge r2 = Builder \r1 -> unsafeMerge r1 r2 值:

intermediate

无法提取&#34;从这里:

> intermediate = unionMerge name {email: "someone@example.com"}
> unionMerge age intermediate

并且它只被下一个构建器消耗一次,即> build (merge name >>> merge age) {email: "someone@example.com"}

TYPESYSTEM评论:

由于来自merge age的{​​{1}}类型类,Purescript类型系统似乎可以处理此问题:

Union

这有什么&#34;魔法类型&#34; (来源:slide 23):

Prim

旧方法(仍然有效,但不是首选):

purescript-records个软件包公开了unionMerge,它完全符合您的要求(在新的psci中,我们不必使用The Union type class is used to compute the union of two rows of types (left-biased, including duplicates). The third type argument represents the union of the first two. ):

Union r1 r2 r3 | r1 r2 -> r3, r1 r3 -> r2

答案 1 :(得分:5)

目前不可能这样做,因为我们没有办法说一行缺少某些标签或其他标签。可以有一个开放记录类型:

something :: forall r. { name :: String | r } -> ...

但这只允许我们接受带有name和任何其他标签的记录,如果我们想要合并,扩展或减去记录,它对我们没有帮助。

组合任意记录的问题是我们有这样的类型签名:

comb :: forall r1 r2. { | r1 } -> { | r2 } -> ???

我们需要某种方式来说结果(???)是r1r2的联合,但我们也许想说r1' s标签不与r2重叠。

将来可以通过row constraints来实现。