Skip to content

Commit a15f4e6

Browse files
Nicholas Scheelhdgarrood
Nicholas Scheel
authored andcommitted
Update kinds, add newer syntaxes, notes (documentationjs#75)
* Update kinds * Pattern guards * Nested records Fixes documentationjs#18. Todo: Unify with Records.md? * Expand section on type synonyms The example involving `one` did not type check. Now it does. Maybe it would be helpful to think of real-world examples for type synonyms and use those here intead of another example involving Foo & Bar. * Notes that I would find helpful * Do something with the bound variable * Misc. formatting * Typo, hopefully a bit clearer * Grammar
1 parent b4f17b0 commit a15f4e6

File tree

6 files changed

+164
-44
lines changed

6 files changed

+164
-44
lines changed

language/FFI.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ Importing Types
3131
To declare a new abstract type (with no constructors), use `foreign import data` and provide the kind:
3232

3333
```purescript
34-
foreign import data DOMElement :: *
34+
foreign import data DOMElement :: Type
3535
3636
foreign import document :: {
3737
createElement :: String -> DOMElement
3838
}
3939
```
4040

41-
When declaring types in this way, you may declare your type to have any kind, not just `*`. For example, to declare a row of effects:
41+
When declaring types in this way, you may declare your type to have any kind, not just `Type`. For example, to declare a row of effects:
4242

4343
```purescript
44-
foreign import data MyRow :: # !
44+
foreign import data MyRow :: # Effect
4545
```

language/Modules.md

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,20 @@ module B where
2626
import A (runFoo)
2727
```
2828

29-
Values, type constructors, data constructors, and type classes can all be explicitly imported. A type constructor can be followed by a list of associated data constructors to import in parentheses. A double dot (`..`) can be used to import all data constructors for a given type constructor:
29+
Values, operators (wrapped in parentheses), type constructors, data constructors, and type classes can all be explicitly imported. A type constructor can be followed by a list of associated data constructors to import in parentheses. A double dot (`..`) can be used to import all data constructors for a given type constructor:
3030

3131
```purescript
3232
module B where
3333
34-
import A (runFoo, Foo(..), Bar(Bar))
34+
import A (runFoo, (.~), Foo(..), Bar(Bar))
3535
```
3636

37-
Type classes are imported using the `class` keyword:
37+
Type classes are imported using the `class` keyword, kinds with `kind`:
3838

3939
```purescript
4040
module B where
4141
42-
import A (class Fab)
42+
import A (class Fab, kind Effect)
4343
```
4444

4545
### Hiding imports
@@ -59,16 +59,33 @@ Modules can also be imported qualified, which means that their names will not be
5959

6060
```purescript
6161
module Main where
62-
62+
6363
import Data.Array as Array
64-
64+
6565
null = ...
6666
6767
test = Array.null [1, 2, 3]
6868
```
69-
69+
7070
Here, the name ``null`` would ordinarily conflict with ``null`` from ``Data.Array``, but the qualified import solves this problem. ``Data.Array.null`` can be referenced using ``Array.null`` instead.
7171

72+
Operators can also be referenced this way:
73+
```purescript
74+
test' = Array.null ([1, 2, 3] Array.\\ [1, 2, 3])
75+
```
76+
77+
Modules can be merged under the same name, but it is best to use explicit imports to avoid conflicts, in case modules would want to import the same name:
78+
79+
```purescript
80+
module Main where
81+
82+
import Data.String.Regex (split) as Re
83+
import Data.String.Regex.Flags (global) as Re
84+
import Data.String.Regex.Unsafe (unsafeRegex) as Re
85+
86+
split = Re.split (Re.unsafeRegex "[,;:.]\\s+" Re.global)
87+
```
88+
7289
## Module Exports
7390

7491
You can control what gets exported from a module by using an export list. When an export list is used, other modules will only be able to see things which are in the export list. For example:
@@ -95,6 +112,15 @@ module A (module B) where
95112
import B
96113
```
97114

115+
Qualified and explicit imports can be used also:
116+
117+
```purescript
118+
module A (module MoreExports) where
119+
120+
import A.Util (useful, usefulFn) as MoreExports
121+
import A.Type (ADatatype(..)) as MoreExports
122+
```
123+
98124
When re-exporting other modules, all local values and types can also be exported by specifying the module itself as an export:
99125

100126
```purescript

language/Pattern-Matching.md

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,17 @@ Patterns can also be used when introducing functions. For example:
2323
example x y z = x * y + z
2424
```
2525

26-
The following pattern types are supported:
26+
The following forms can be used for matching:
2727

28-
- Wildcard pattern
28+
- Wildcard patterns
2929
- Literal patterns
30-
- Variable pattern
30+
- Variable patterns
3131
- Array patterns
3232
- Constructor patterns
3333
- Record patterns
3434
- Named patterns
35-
- Guards
35+
36+
Guards and pattern guards are also supported.
3637

3738
The exhaustivity checker will introduce a `Partial` constraint for any pattern which is not exhaustive.
3839
By default, patterns must be exhaustive, since this `Partial` constraint will not be satisfied. The error can be silenced, however, by adding a local `Partial` constraint to your function.
@@ -125,16 +126,16 @@ Named Patterns
125126
Named patterns bring additional names into scope when using nested patterns. Any pattern can be named by using the ``@`` symbol:
126127

127128
```purescript
128-
f a@[_, _] = true
129-
f _ = false
129+
f a@[_, _] = a
130+
f _ = []
130131
```
131132

132133
Here, in the first pattern, any array with exactly two elements will be matched and bound to the variable `a`.
133134

134135
Guards
135136
------
136137

137-
Guards are used to impose additional constraints inside a pattern using boolean-valued expressions, and are introduced with a pipe after the pattern::
138+
Guards are used to impose additional constraints inside a pattern using boolean-valued expressions, and are introduced with a pipe after the pattern:
138139

139140
```purescript
140141
evens :: List Int -> Int
@@ -149,3 +150,43 @@ When using patterns to define a function at the top level, guards appear after a
149150
greater x y | x > y = true
150151
greater _ _ = false
151152
```
153+
154+
To be considered exhaustive, guards must clearly include a case that is always true. Even though the following makes perfect sense, the compiler cannot determine that is is exhaustive:
155+
156+
```purescript
157+
compare :: Int -> Int -> Ordering
158+
compare x y
159+
| x > y = GT
160+
| x == y = EQ
161+
| x < y = LT
162+
```
163+
164+
Either of these will work, since they clearly include a final case:
165+
166+
```purescript
167+
compare x y
168+
| x > y = GT
169+
| x < y = LT
170+
| otherwise = EQ
171+
172+
compare x y | x > y = GT
173+
compare x y | x < y = LT
174+
compare _ _ = EQ
175+
```
176+
177+
(The name `otherwise` is a synonym for `true` commonly used in guards.)
178+
179+
Pattern Guards
180+
--------------
181+
182+
Pattern guards extend guards with pattern matching, notated with a left arrow. A pattern guard will succeed only if the computation on the right side of the arrow matches the pattern on the left.
183+
184+
For example, we can apply a function `fn` to an argument `x`, succeeding only if
185+
`fn` returns `Just y` for some `y`, binding `y` at the same time:
186+
187+
```purescript
188+
bar x | Just y <- fn x = ... -- x and y are both in scope here
189+
```
190+
191+
Pattern guards can be very useful for expressing certain types of control flow when
192+
using algebraic data types.

language/Records.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ Fields of records can be accessed using a dot, followed by the label of the fiel
2424

2525
`{ ... }` is just syntactic sugar for the `Record` type constructor, so `{ language :: String }` is the same as `Record ( language :: String )`.
2626

27-
The Record type constructor is parameterized by a row of types. In kind notation, `Record` has kind `# * -> *`. That is, it takes a row of types to a type.
27+
The Record type constructor is parameterized by a row of types. In kind notation, `Record` has kind `# Type -> Type`. That is, it takes a row of types to a type.
2828

29-
`( language :: String )` denotes a row of types (something of kind `# *`), so it can be passed to `Record` to construct a type, namely `Record ( language :: String )`.
29+
`( language :: String )` denotes a row of types (something of kind `# Type`), so it can be passed to `Record` to construct a type, namely `Record ( language :: String )`.
3030

3131
## Extending Records
3232

@@ -42,7 +42,7 @@ that can then be extended like:
4242
type Language = Lang ( country :: String )
4343
```
4444

45-
The `Language` type synonym would then be equivalent to `{ language :: String, country :: String }`.
45+
The `Language` type synonym would then be equivalent to `{ language :: String, country :: String }`. Note that parentheses must be used for the extension, since `l` has to be a row kind not a record type.
4646

4747
## Wildcards
4848

language/Syntax.md

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,20 +234,39 @@ This is equivalent to:
234234
\rec -> rec.propertyName
235235
```
236236

237+
These work with any number of levels:
238+
239+
``` purescript
240+
_.nested.property.name
241+
```
242+
237243
### Record Updates
238244

239245
Properties on records can be updated using the following syntax:
240246

241247
``` purescript
242-
rec { key1 = value1, ..., keyN = valueN }
248+
rec { key1 = value1, ..., keyN = valueN, nestedKey { subKey = value, ... } }
243249
```
244250

251+
Some or all of the keys may be updated at once, and records inside of records can also be updated.
252+
245253
For example, the following function increments the `foo` property on its argument:
246254

247255
``` purescript
248256
\rec -> rec { foo = rec.foo + 1 }
249257
```
250258

259+
[Nested record updates](https://liamgoodacre.github.io/purescript/records/2017/01/29/nested-record-updates.html) look like this:
260+
261+
``` purescript
262+
r = { val: -1
263+
, level1: { val: -1
264+
, level2: { val: -1 }
265+
}
266+
}
267+
r' = r { level1 { val = 1 } }
268+
```
269+
251270
Wildcards can also be used in updates to produce a partially applied update:
252271

253272
``` purescript

0 commit comments

Comments
 (0)