diff --git a/spec.md b/spec.md index f6cc87a..01deb65 100644 --- a/spec.md +++ b/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. \ No newline at end of file +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 +``` \ No newline at end of file