如何在 PureScript 中组合记录类型的行?(是否有任何替代 PureScript 0.12.0 中的 Union 类型类的方法?) [英] How to combine rows of record types in PureScript? (Is there any alternative to the Union typeclass in PureScript 0.12.0?)

查看:81
本文介绍了如何在 PureScript 中组合记录类型的行?(是否有任何替代 PureScript 0.12.0 中的 Union 类型类的方法?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:我有许多常见字段的不同记录类型.如何在记录类型定义中包含"公共字段?

Problem: I have different record types with many common fields. How could I "include" the common fields in the record type definitions?

示例:

newtype RecordType1 = RecordType1 { a :: Int, b :: Int, y :: String }
newtype RecordType2 = RecordType2 { a :: Int, b :: Int, z :: Boolean } 

如何在 PureScript 中编写等价物?

How to write the equivalent in PureScript?

newtype RecordType1 = RecordType1 { CommonFields, y :: String }
newtype RecordType2 = RecordType2 { CommonFields, z :: Boolean }

Union="noreferrer">PureScript 类型系统概述 可能是我要找的……但它似乎从 PureScript 0.12.0 开始就没有了.

The type class Union mentioned in An Overview of the PureScript Type System could be what I look for... but it seems to be out since PureScript 0.12.0.

有什么推荐吗?有什么我遗漏的吗?

Any recommendations? Is there anything I'm missing?

谢谢!

推荐答案

PureScript 具有用于组合记录的特殊语法:

PureScript has a special syntax for combining records:

type Common = ( a :: Int, b :: Int )
type Record1 = { y :: String | Common }
type Record2 = { z :: Boolean | Common }
newtype RecordType3 = RecordType3 { w :: Number | Common }

请注意,Common 的定义使用括号,而不是花括号.这是因为Common 是一个,而不是一个记录.你可以用它做一个记录:

Note that the definition of Common uses parentheses, not curly braces. That is because Common is a row, not a record. You can make a record out of it though:

type CommonRec = Record Common 
-- equivalent to:  CommonRec = { a :: Int, b :: Int }

事实上,大括号表示法只是将 Record 应用到一行的语法糖.表达式 { xyz } 被脱糖为 Record ( xyz ).

In fact, the curly braces notation is just syntactic sugar for applying Record to a row. An expression { xyz } gets desugared to Record ( xyz ).

您也可以使用管道"语法来扩展行:

You can use the "pipe" syntax to extend rows as well:

type CommonPlusFoo = ( foo :: Bar | Common )
type RecWithFoo = { x :: Int | CommonPlusFoo }

<小时>

您还可以通过提供 Common 作为类型参数来使您的记录类型多态:


You can also make your record types polymorphic by providing Common as a type parameter:

type Record1Poly r = { y :: String | r }
type Record1 = Record1Poly Common

这对于编写处理部分记录的函数非常方便,例如:

This is very handy for writing functions that work with partial records, e.g.:

updateName :: forall r. { name :: String | r } -> { name :: String | r }
updateName x = x { name = "Mr. " <> x.name }

jones = { name: "Jones", occupation: "Plumber" }
mrJones = updateName jones  -- mrJones = { name: "Mr. Jones", occupation: "Plumber" }

在本例中,该函数可以处理任何具有 name 字段的记录,而不管它可能还有什么.

In this example, the function can work with any record that has a name field, regardless of what else it might have.

最后,要表达一个空行,使用空括号:

Finally, to express an empty row, use empty parens:

type Record1Poly r = { y :: String | r }
type Record1 = Record1Poly Common
type OnlyY = Record1Poly ()

<小时>

关于一个稍微不相关的主题,请注意 PureScript 中的记录与 Haskell 中的记录不同.例如,上面的 Record1Record2 是真正的 PureScript ad-hoc 可扩展记录(Haskell 没有的东西),但是 RecordType3 是一个newtype 有一个构造函数,其参数是一条记录.


On a slightly unrelated topic, note that records in PureScript are not the same as records in Haskell. For example, above Record1 and Record2 are true PureScript ad-hoc extensible records (something that Haskell doesn't have), but RecordType3 is a newtype that has one constructor whose parameter is a record.

一个重要的区别是,与 Haskell 不同,这行不通:

One important difference is that, unlike Haskell, this wouldn't work:

 x = RecordType3 { w: 42.0, a: 1, b: 2 }
 y = w x

表达式 wx(甚至表达式 xw)不能编译,因为 RecordType3 本身不是记录,它是一个新类型包装一个记录.为了让 w 脱离它,你需要先匹配构造函数:

The expression w x (or even expression x.w) doesn't compile, because RecordType3 is not itself a record, it's a newtype that wraps a record. In order to get w out of it you need to match on the constructor first:

 (RecordType3 k) = x
 y = k.w

或者将其包装为访问器函数:

Or wrap that as an accessor function:

 unRecordType3 (RecordType3 k) = k
 y = (unRecordType3 x).w

在实践中,如果您以 Haskell 的心态处理记录,这真的很不方便.相反,您想要在 PureScript 中做的是更喜欢裸"记录(如我上面示例中的 Record1Record2),并且只能将它们包装在 newtype 中 当你真的需要时.

In practice this is really inconvenient if you're approaching records with a Haskell mindset. Instead, what you want to do in PureScript is prefer "naked" records (like Record1 and Record2 in my example above) and only resort to wrapping them in newtype when you really have to.

这篇关于如何在 PureScript 中组合记录类型的行?(是否有任何替代 PureScript 0.12.0 中的 Union 类型类的方法?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆