Update spec.md

This commit is contained in:
2025-09-12 13:59:29 +02:00
parent 7e8739cdd8
commit 4fba995390

90
spec.md
View File

@@ -21,15 +21,14 @@ Advanced (uncommon) types:
## Functions
```
# the type of msg is: List[Char] -> List[Char]
def msg(username: List[Char]) : List[Char] {
def msg(username: List[Char]) -> List[Char] {
"Hello, " ++ username ++ "!" # last expr is returned
}
# the type of main is: Unit -> Unit
def main() {
# the type of main is: Unit -> IO[Unit]
def main() -> IO[Unit] {
print("hi")
}
main()
```
## Anonymus functions
@@ -40,7 +39,7 @@ List.map(li, x:Num -> x * 2)
## Simple, forward type-inference
```
def zero () : Flt32 {
def zero () -> Flt32 {
3.1 # error: got Num, but expected Flt32
}
```
@@ -48,7 +47,7 @@ def zero () : Flt32 {
## Partial function applications
```
# type of add is Num -> Num -> Num
def add(a: Num, b: Num) : Num {
def add(a: Num, b: Num) -> Num {
a + b
}
@@ -81,20 +80,20 @@ all operators:
type User = { name: List[Char] }
type DbUser = { name: List[Char], pass: List[Char] }
def example4(u: User) : List[Char] {
def example4(u: User) -> List[Char] {
u:name # colon is used to access fields
}
def example(u: User) : DbUser {
def example(u: User) -> DbUser {
u with pass: "1234"
# has type { name: List[Char], pass: List[Char] }
}
def example2() : {name: List[Char], pass: List[Char]} {
def example2() -> {name: List[Char], pass: List[Char]} {
{name:"abc", pass:"123"}
}
def example3() : User {
def example3() -> User {
example2() # {name:.., pass:...} can automatically decay to {name:...}
}
```
@@ -106,36 +105,36 @@ type Option[t] =
| 'Some t
# the tags of unions are weakly attached to the types, but won't decay unless they have to
def example(n: Num) : Num {
def example(n: Num) -> Num {
let x = 'MyTag n # type of x is 'MyTag Num
x # tag gets removed because target type is Num
}
def example2(n: Num) : Option[Num] {
def example2(n: Num) -> Option[Num] {
'Some n
}
def example3-invalid() : Option[Num] {
def example3-invalid() -> Option[Num] {
Unit # error: can't convert type `Unit` into type `'Err Unit | 'Some Num`
# Either label the expression with 'Err,
# or change the return type to Option[Unit], and label the expression with 'Some
}
def exampe4(): Option[Num] {
def exampe4() -> Option[Num] {
'Err Unit
# type of this expression is: `'Err Unit`
# enums can automatically cast, if all the cases from the source enum also exists in the target enum,
# which they do here: `'Err Unit` is a case in `'Err Unit | Num`
}
def example5-error(): Option[Num] {
def example5-error() -> Option[Num] {
let x = ( 'Err Unit ) :: Option[Unit]
x
# error: can't convert type `'Err Unit | 'Some Unit` into type `'Err Unit | 'Some Num`
# The case `'Some Unit` does not exist in the target `'Err Unit | 'Some Num`
}
def example6-error(): Option[Unit] {
def example6-error() -> Option[Unit] {
let x = 'Error Unit
x
# in this case, the enum tag does not decay, like in `example`,
@@ -150,6 +149,8 @@ def example6-error(): Option[Unit] {
### pattern 1: labelled arguments
```
def [t] List.remove_prefix(prefix: List[t], list: 'from List[t])
List.remove_prefix([1,2], 'from [1,2,3,4])
```
## automatic return types
@@ -194,7 +195,7 @@ def [t] Match.`a++b`(
then you can do:
```
type Token = 'Public Unit | 'Private Unit | 'Err Unit;
type Token = 'Public | 'Private | 'Err
def example(li: List[Char]) -> {t:Token,rem:List[Char]} {
match li {
"public" ++ rem -> {t: 'Public Unit, rem:rem}
@@ -322,17 +323,27 @@ def example() -> 'Int | 'UInt | 'Byte | 'Char {
## Extensible unions
```
type Plan = dyn 'Plan;
# ^ this is not a union variant tag, but a quoted identifier
extensible union Plan
extend Plan with 'ReadlnPlan
extend Plan with 'WritelnPlan
extend Plan with 'ReadlnPlan Unit
extend Plan with 'WritelnPlan Unit
# pattern matching against these is always non-exhaustive.
# can only pattern match with the imported extensions
```
## Any type
in the stdlib:
```
extensible union Any
type Any.LambdaCalc = 'Apply {fn: Any.LambdaCalc, arg: Any.LambdaCalc}
| 'Scope {idx: Uint}
| 'Abstr {inner: Any.LambdaCalc}
def Any.toLambda(a: Any) -> Any.LambdaCalc
```
It gets automatically extended with every type ever used.
## Lenses
In the stdlib:
```
@@ -365,6 +376,39 @@ myHeader with header:text: "new meta:header:text value"
## Pure IO
Something like this is done in the stdlib:
```
TODO
extensible union IO.Plan[r]
type IO[t] = 'Just {value: t}
| 'More template r, f: {plan: IO.Plan[r], then: r -> IO[f], finally: f -> t}
def [a,b] `await a (a->b)`(io: IO[a], then: a -> b) -> IO[b] {
match io {
'Just {value} -> 'Just {value: then(value)},
'More &a {finally,...} -> a with finally: r -> then(finally(r))
}
}
# in stdio:
extend IO.Plan[Uint8] with 'stdio.ReadByte {stream: Int32}
def stdio.getchar : IO[Uint8] = 'More {plan: 'stdio.ReadByte {stream: 0}, then: by -> 'Just by[0], finally: x->x}
def main() -> IO[Unit]
```
the runtime does something like this:
```
def [a] RUNTIME_EVAL(io: IO[a]) -> a {
match io {
'Just {value} -> value
'More {plan, then, finally} -> finally(RUNTIME_EVAL(then(match plan {
'ReadStream {stream} -> 'ReadStreamIOResult {data: impure perform the io here lol}
_ -> impure error here "this runtime doesn't support this kind of IO" or sth
})))
}
}
def RUNTIME_ENTRY() {
RUNTIME_EVAL ( main() )
}
```