Mat*_*ois 3 union records rows purescript
问题:我有许多常见字段的不同记录类型.我如何"包含"记录类型定义中的公共字段?
例:
newtype RecordType1 = RecordType1 { a :: Int, b :: Int, y :: String }
newtype RecordType2 = RecordType2 { a :: Int, b :: Int, z :: Boolean }
Run Code Online (Sandbox Code Playgroud)
如何在PureScript中编写等效的?
newtype RecordType1 = RecordType1 { CommonFields, y :: String }
newtype RecordType2 = RecordType2 { CommonFields, z :: Boolean }
Run Code Online (Sandbox Code Playgroud)
" PureScript类型系统概述"中Union提到的类型类可能是我所寻求的......但它似乎是自PureScript 0.12.0以来的.
有什么建议?有什么我想念的吗?
谢谢!
Fyo*_*kin 15
PureScript具有用于组合行的特殊语法:
type Common = ( a :: Int, b :: Int )
type Record1 = { y :: String | Common }
type Record2 = { z :: Boolean | Common }
newtype RecordType3 = RecordType3 { w :: Number | Common }
Run Code Online (Sandbox Code Playgroud)
请注意,Common使用括号的定义,而不是花括号.那是因为Common是一行,而不是记录.你可以创建一个记录:
type CommonRec = Record Common
-- equivalent to: CommonRec = { a :: Int, b :: Int }
Run Code Online (Sandbox Code Playgroud)
实际上,花括号符号只是用于Record行的语法糖.表达{ xyz }变得卑鄙Record ( xyz ).
您也可以使用"管道"语法来扩展行:
type CommonPlusFoo = ( foo :: Bar | Common )
type RecWithFoo = { x :: Int | CommonPlusFoo }
Run Code Online (Sandbox Code Playgroud)
您还可以通过提供Common类型参数来使记录类型具有多态性:
type Record1Poly r = { y :: String | r }
type Record1 = Record1Poly Common
Run Code Online (Sandbox Code Playgroud)
这对于编写使用部分记录的函数非常方便,例如:
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" }
Run Code Online (Sandbox Code Playgroud)
在此示例中,该函数可以处理具有name字段的任何记录,而不管它可能具有什么.
最后,要表示一个空行,请使用空的parens:
type Record1Poly r = { y :: String | r }
type Record1 = Record1Poly Common
type OnlyY = Record1Poly ()
Run Code Online (Sandbox Code Playgroud)
在一个稍微不相关的主题上,请注意PureScript中的记录与Haskell中的记录不同.例如,上面Record1和Record2是真正的PureScript特设扩展记录(的东西,Haskell没有),而且RecordType3是具有一个构造函数,其参数是一个记录一个NEWTYPE.
一个重要的区别是,与Haskell不同,这不起作用:
x = RecordType3 { w: 42.0, a: 1, b: 2 }
y = w x
Run Code Online (Sandbox Code Playgroud)
表达式w x(甚至表达式x.w)不会编译,因为RecordType3它本身不是记录,它是包装记录的新类型.为了w摆脱它,你需要首先匹配构造函数:
(RecordType3 k) = x
y = k.w
Run Code Online (Sandbox Code Playgroud)
或者将其作为访问者函数包装:
unRecordType3 (RecordType3 k) = k
y = (unRecordType3 x).w
Run Code Online (Sandbox Code Playgroud)
实际上,如果您正在接近具有Haskell思维模式的记录,这真的很不方便.相反,你想在PureScript做的是更喜欢"裸"的记录(如Record1与Record2上面我的例子),只有诉诸于包装它们newtype当你真的不得不这样做.
小智 8
费奥多尔的回答是正确的。但是,如果需要,还有另一种简洁的语法可以组合许多行类型。
通常,如果您有许多要组合的记录类型,您可以这样做:
type Foo r = ( x :: String | r )
type Bar r = ( y :: Int | r )
type FooBar r = Foo (Bar r)
Run Code Online (Sandbox Code Playgroud)
但是如果你有多个组合,或者名称太长,这会变得很麻烦:
type ThisIsAFoo r = ( x :: String | r )
type ThisIsABar r = ( y :: Int | r )
type ThisIsABaz r = ( z :: Number | r )
type ThisIsAFooBarBaz r = ThisIsAFoo (ThisIsABar (ThisIsABaz r))
Run Code Online (Sandbox Code Playgroud)
所以你可以使用一个很好的语法将它们组合到 Type 模块中:
import Type.Row (type (+))
type ThisIsAFooBarBaz r = ThisIsAFoo + ThisIsABar + ThisIsABaz + r
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
365 次 |
| 最近记录: |