Update spec.md
This commit is contained in:
90
spec.md
90
spec.md
@@ -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() )
|
||||
}
|
||||
```
|
Reference in New Issue
Block a user