Update spec.md

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

92
spec.md
View File

@@ -21,15 +21,14 @@ Advanced (uncommon) types:
## Functions ## Functions
``` ```
# the type of msg is: List[Char] -> List[Char] # 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 "Hello, " ++ username ++ "!" # last expr is returned
} }
# the type of main is: Unit -> Unit # the type of main is: Unit -> IO[Unit]
def main() { def main() -> IO[Unit] {
print("hi") print("hi")
} }
main()
``` ```
## Anonymus functions ## Anonymus functions
@@ -40,7 +39,7 @@ List.map(li, x:Num -> x * 2)
## Simple, forward type-inference ## Simple, forward type-inference
``` ```
def zero () : Flt32 { def zero () -> Flt32 {
3.1 # error: got Num, but expected Flt32 3.1 # error: got Num, but expected Flt32
} }
``` ```
@@ -48,7 +47,7 @@ def zero () : Flt32 {
## Partial function applications ## Partial function applications
``` ```
# type of add is Num -> Num -> Num # type of add is Num -> Num -> Num
def add(a: Num, b: Num) : Num { def add(a: Num, b: Num) -> Num {
a + b a + b
} }
@@ -81,20 +80,20 @@ all operators:
type User = { name: List[Char] } type User = { name: List[Char] }
type DbUser = { name: List[Char], pass: 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 u:name # colon is used to access fields
} }
def example(u: User) : DbUser { def example(u: User) -> DbUser {
u with pass: "1234" u with pass: "1234"
# has type { name: List[Char], pass: List[Char] } # 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"} {name:"abc", pass:"123"}
} }
def example3() : User { def example3() -> User {
example2() # {name:.., pass:...} can automatically decay to {name:...} example2() # {name:.., pass:...} can automatically decay to {name:...}
} }
``` ```
@@ -106,36 +105,36 @@ type Option[t] =
| 'Some t | 'Some t
# the tags of unions are weakly attached to the types, but won't decay unless they have to # 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 let x = 'MyTag n # type of x is 'MyTag Num
x # tag gets removed because target type is Num x # tag gets removed because target type is Num
} }
def example2(n: Num) : Option[Num] { def example2(n: Num) -> Option[Num] {
'Some n '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` Unit # error: can't convert type `Unit` into type `'Err Unit | 'Some Num`
# Either label the expression with 'Err, # Either label the expression with 'Err,
# or change the return type to Option[Unit], and label the expression with 'Some # or change the return type to Option[Unit], and label the expression with 'Some
} }
def exampe4(): Option[Num] { def exampe4() -> Option[Num] {
'Err Unit 'Err Unit
# type of this expression is: `'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, # 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` # 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] let x = ( 'Err Unit ) :: Option[Unit]
x x
# error: can't convert type `'Err Unit | 'Some Unit` into type `'Err Unit | 'Some Num` # 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` # 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 let x = 'Error Unit
x x
# in this case, the enum tag does not decay, like in `example`, # 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 ### pattern 1: labelled arguments
``` ```
def [t] List.remove_prefix(prefix: List[t], list: 'from List[t]) 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 ## automatic return types
@@ -194,7 +195,7 @@ def [t] Match.`a++b`(
then you can do: 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]} { def example(li: List[Char]) -> {t:Token,rem:List[Char]} {
match li { match li {
"public" ++ rem -> {t: 'Public Unit, rem:rem} "public" ++ rem -> {t: 'Public Unit, rem:rem}
@@ -322,17 +323,27 @@ def example() -> 'Int | 'UInt | 'Byte | 'Char {
## Extensible unions ## Extensible unions
``` ```
type Plan = dyn 'Plan; extensible union Plan
# ^ this is not a union variant tag, but a quoted identifier
extend Plan with 'ReadlnPlan extend Plan with 'ReadlnPlan Unit
extend Plan with 'WritelnPlan extend Plan with 'WritelnPlan Unit
# pattern matching against these is always non-exhaustive. # pattern matching against these is always non-exhaustive.
# can only pattern match with the imported extensions # 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 ## Lenses
In the stdlib: In the stdlib:
``` ```
@@ -365,6 +376,39 @@ myHeader with header:text: "new meta:header:text value"
## Pure IO ## 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() )
}
``` ```