v0.0.10: hide record fields & union variants, extensible unions, lenses
This commit is contained in:
96
spec.md
96
spec.md
@@ -73,6 +73,7 @@ all operators:
|
||||
- `List[t] ++ List[t]`: list concatenation
|
||||
- `value :: t` (explicitly specify type of value, useful for down-casting structs, or just code readability; does not perform casting)
|
||||
- `list[index]`
|
||||
- `a => b`: lens compose
|
||||
|
||||
## non-nominal struct types
|
||||
```
|
||||
@@ -80,6 +81,10 @@ all operators:
|
||||
type User = { name: List[Char] }
|
||||
type DbUser = { name: List[Char], pass: List[Char] }
|
||||
|
||||
def example4(u: User) : List[Char] {
|
||||
u:name # colon is used to access fields
|
||||
}
|
||||
|
||||
def example(u: User) : DbUser {
|
||||
u with pass: "1234"
|
||||
# has type { name: List[Char], pass: List[Char] }
|
||||
@@ -245,18 +250,18 @@ Export signature file `List.li`:
|
||||
type List[t] = 'End | 'Cons {head:t, tail:List[t]}
|
||||
|
||||
# not providing a function body makes it a function signature definition
|
||||
def [t] `a++b`(a: List[t], b: List[t]) -> List[t];
|
||||
def [t] `a++b`(a: List[t], b: List[t]) -> List[t]
|
||||
|
||||
def [t] Match.`a++b`(
|
||||
value: List[t],
|
||||
l: List[t],
|
||||
r: MatchUtil.Var[List[t]]
|
||||
) -> Option[{ r: List[t] }];
|
||||
) -> Option[{ r: List[t] }]
|
||||
```
|
||||
|
||||
Import signature file `Option.li`:
|
||||
```
|
||||
type Option[t] = 'None | 'Some t;
|
||||
type Option[t] = 'None | 'Some t
|
||||
```
|
||||
|
||||
Compilation unit `List.lu`:
|
||||
@@ -279,4 +284,87 @@ Each compilation unit gets compiled to implementation-specific bytecode.
|
||||
|
||||
Templated functions can only be compiled partially during a compilation unit. This will impact compile speeds.
|
||||
|
||||
Avoid templated functions wherever possible.
|
||||
Avoid templated functions wherever possible.
|
||||
|
||||
## Hide record fields in module signatures
|
||||
Signatue:
|
||||
```
|
||||
type User = {name: List[Char], ...}
|
||||
# the ... is used to indicate that this is a partial type definition
|
||||
# User, as given here, can not be constructed, but name can be accessed
|
||||
```
|
||||
Compilation unit:
|
||||
```
|
||||
type User = {name: List[Char], password: List[Char]}
|
||||
```
|
||||
|
||||
## Hide union variants in module signatures
|
||||
Signature:
|
||||
```
|
||||
type DType = 'Int | 'UInt | 'Byte | ...
|
||||
# users of this can never do exhaustive pattern matching on this
|
||||
```
|
||||
Compilation unit:
|
||||
```
|
||||
type DType = 'Int | 'UInt | 'Byte
|
||||
# this compilation unit can actually do exhaustive pattern matching on this
|
||||
```
|
||||
|
||||
## Note on hidden union variants / record fields
|
||||
To make these work, the following is legal:
|
||||
```
|
||||
def example() -> 'Int | 'UInt | ...
|
||||
|
||||
def example() -> 'Int | 'UInt | 'Byte | 'Char {
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
## Extensible unions
|
||||
```
|
||||
type Plan = dyn 'Plan;
|
||||
# ^ this is not a union variant tag, but a quoted identifier
|
||||
|
||||
extend Plan with 'ReadlnPlan
|
||||
extend Plan with 'WritelnPlan
|
||||
|
||||
# pattern matching against these is always non-exhaustive.
|
||||
# can only pattern match with the imported extensions
|
||||
|
||||
```
|
||||
|
||||
## Lenses
|
||||
In the stdlib:
|
||||
```
|
||||
type Lens[t,f] = {get: t -> f, set: t -> f -> t}
|
||||
|
||||
def [a,b,c] `a=>b`(x: Lens[a,b], y: Lens[b,c]) -> Lens[a,c] {
|
||||
{
|
||||
get: t:a -> y:get(x:get(t)),
|
||||
set: t:a -> f:c -> x:set(t, y:set(x:get(t), f))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Since `a:f1:f2` is the field access syntax, the lens creation syntax is similar: `&Type:field1:field2`
|
||||
|
||||
So you can do:
|
||||
```
|
||||
type Header = {text: String, x: Num}
|
||||
type Meta = {header: Header, name: String}
|
||||
|
||||
&Header:header:text (myHeader, "new meta:header:text value")
|
||||
# which is identical to:
|
||||
(&Header:header => &Meta:text) (myHeader, "new meta:header:text value")
|
||||
```
|
||||
|
||||
However, it is cleaner to use `with`:
|
||||
```
|
||||
myHeader with header:text: "new meta:header:text value"
|
||||
```
|
||||
|
||||
|
||||
## Pure IO
|
||||
```
|
||||
TODO
|
||||
```
|
Reference in New Issue
Block a user