gpt4 book ai didi

union - 如何在 PureScript 中组合记录类型的行? (PureScript 0.12.0 中的 Union 类型类有什么替代品吗?)

转载 作者:行者123 更新时间:2023-12-01 22:57:09 25 4
gpt4 key购买 nike

问题:我有许多常见字段的不同记录类型。我如何在记录类型定义中“包含”公共(public)字段?

例子:

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

如何在 PureScript 中编写等价物?
newtype RecordType1 = RecordType1 { CommonFields, y :: String }
newtype RecordType2 = RecordType2 { CommonFields, z :: Boolean }

类型类 Union An Overview of the PureScript Type System 中提到可能是我要找的东西......但它似乎从 PureScript 0.12.0 开始就出来了。

有什么建议吗?有什么我想念的吗?

谢谢!

最佳答案

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

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

注意 Common 的定义使用括号,而不是花括号。那是因为 Common是一行,不是记录。不过,您可以记录下来:
type CommonRec = Record Common 
-- equivalent to: CommonRec = { a :: Int, b :: Int }

事实上,花括号符号只是应用 Record 的语法糖。到一排。一个表达式 { xyz }脱糖至 Record ( xyz ) .

您也可以使用“管道”语法来扩展行:
type CommonPlusFoo = ( foo :: Bar | Common )
type RecWithFoo = { x :: Int | CommonPlusFoo }

您还可以通过提供 Common 使您的记录类型具有多态性。作为类型参数:
type Record1Poly r = { y :: String | r }
type Record1 = Record1Poly Common

这对于编写处理部分记录的函数非常方便,例如:
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 的记录。字段,不管它可能还有什么。

最后,要表达一个空行,请使用空括号:
type Record1Poly r = { y :: String | r }
type Record1 = Record1Poly Common
type OnlyY = Record1Poly ()

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

一个重要的区别是,与 Haskell 不同,这是行不通的:
 x = RecordType3 { w: 42.0, a: 1, b: 2 }
y = w x

表达式 w x (甚至表达式 x.w )无法编译,因为 RecordType3它本身不是记录,它是一种包装记录的新类型。为了得到 w其中你需要首先匹配构造函数:
 (RecordType3 k) = x
y = k.w

或者将其包装为访问器函数:
 unRecordType3 (RecordType3 k) = k
y = (unRecordType3 x).w

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

关于union - 如何在 PureScript 中组合记录类型的行? (PureScript 0.12.0 中的 Union 类型类有什么替代品吗?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51986883/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com