-
Notifications
You must be signed in to change notification settings - Fork 301
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add section on record puns and type synonyms for records #330
base: master
Are you sure you want to change the base?
Changes from all commits
78ff5ce
b77b502
1441932
9453c1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,13 +20,36 @@ Fields of records can be accessed using a dot, followed by the label of the fiel | |
["Functional Programming","JavaScript"] | ||
``` | ||
|
||
Type synonyms for record types are created with the `type` keyword: | ||
|
||
```purs | ||
type Point = | ||
{ x :: Number | ||
, y :: Number | ||
} | ||
``` | ||
|
||
## Kinds | ||
|
||
`{ ... }` is just syntactic sugar for the `Record` type constructor, so `{ language :: String }` is the same as `Record ( language :: String )`. | ||
`{ ... }` is syntactic sugar for the `Record` type constructor. This type constructor is parameterized by a row of types: | ||
|
||
The Record type constructor is parameterized by a row of types. In kind notation, `Record` has kind `Row Type -> Type`. That is, it takes a row of types to a type. | ||
```purescript | ||
-- these types are equivalent | ||
type Language = { language :: String } | ||
type Language' = Record ( language :: String ) | ||
``` | ||
|
||
`( language :: String )` denotes a row of types (something of kind `Row Type`), so it can be passed to `Record` to construct a type, namely `Record ( language :: String )`. | ||
A `Record` is constructed from a row type and represents a product type in which all fields in the row type are present. Using kind notation, `Record` has the kind `Row Type -> Type` -- that is, it takes a row of types and produces a type. | ||
|
||
Because `( language :: String )` denotes a row of types (and therefore has the kind `Row Type`), it can be passed to the `Record` constructor or to the `{ ... }` syntax for `Record` to construct a type: | ||
|
||
```purescript | ||
type LanguageRow = ( language :: String ) -- has kind Row Type | ||
|
||
-- these are equivalent | ||
type Language = Record LanguageRow | ||
type Language' = { | LanguageRow } | ||
``` | ||
|
||
## Extending Records | ||
|
||
|
@@ -79,6 +102,61 @@ A record update function can also be defined by using an `_` inplace of the reco | |
_ { fieldName = newValue } | ||
``` | ||
|
||
## Record Puns | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like this section, but there's some overlap with the language syntax documentation: I think we should merge that content into this file and then update the language syntax file to link here. It makes more sense for that content to be in this section and just a link be in that file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think that file has good content and it could be used to inform what you've written here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I'm not seeing any "Record Pun" examples in Syntax.md, but I agree that there are duplicated themes across Records.md, Syntax,md, and Pattern-Matching.md. Whether this should be reorganized seems like a bigger discussion. Maybe something to tackle as part of #344 So for now, I'm thinking we should hold-off on making changes across multiple files. |
||
|
||
_Record puns_ enable concise code when record fields have the same name as other values. This feature is useful for constructing records and pattern matching. | ||
|
||
### Constructing | ||
|
||
```purs | ||
origin :: Point | ||
origin = { x, y } | ||
-- origin = { x: x, y: y } -- Equivalent | ||
where | ||
x = 0.0 | ||
y = 0.0 | ||
``` | ||
|
||
### Pattern Matching | ||
|
||
```purs | ||
showPoint :: Point -> String | ||
showPoint { x, y } = show x <> ", " <> show y | ||
-- showPoint { x : x, y : y } = show x <> ", " <> show y -- Equivalent | ||
``` | ||
|
||
### Not for Record Updates | ||
|
||
Note that puns may not be used for record updates. | ||
|
||
```purescript | ||
setX :: Number -> Point -> Point | ||
setX x point = point { x = x } | ||
-- setX x point = point { x } -- Not allowed | ||
``` | ||
|
||
## Further Record Operations | ||
|
||
The [`record`](https://pursuit.purescript.org/packages/purescript-record) package enables additional record operations, such as `merge`, `union`, and efficient ways to create records (see [Record.Builder](https://pursuit.purescript.org/packages/purescript-record/docs/Record.Builder)). | ||
|
||
Here's an example of using the `disjointUnion` function to add a `z` field to a `Point` record. The `to3d` function merges the original record `p` with another record `{ z }` created from this new `Number`: | ||
|
||
```purescript | ||
import Record (disjointUnion) | ||
|
||
type Point3d = | ||
{ x :: Number | ||
, y :: Number | ||
, z :: Number | ||
} | ||
|
||
to3d :: Point -> Number -> Point3d | ||
to3d p z = disjointUnion p { z } | ||
|
||
-- Equivalent to: | ||
to3d p z = { x: p.x, y: p.y, z } | ||
``` | ||
|
||
## Field Names | ||
|
||
Symbols which are illegal value identifiers, such as title-cased identifiers or ones containing spaces, can be used to identify a field by enclosing it in double-quotes: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is covered later in this documentation, but I suppose it's information worth stating right away. Why not stick with the existing example in this section, though?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to define
Point
, since it's used in later examples.