Continuing to toss ideas around and work on different parts of the base design.

This commit is contained in:
Pat Garrity 2024-01-27 22:00:47 -06:00
parent 5854408466
commit 218647484d
Signed by: pfm
GPG key ID: 5CA5D21BAB7F3A76
11 changed files with 197 additions and 54 deletions

View file

@ -5,19 +5,16 @@ _Constants_ are definitions which provide a name and explicit type for some
constant.
```
const weak_pi: Float64 is 3.14
const my_name: String is "Pat"
const weak_pi: Float64 := 3.14
const my_name: String := "Pat"
```
In general:
```
const <name>: <type> is <value>
const <name>: <type> := <value>
```
Since a constant is categorized as a [definition](general-syntax.md#definitions)
is uses the `is` keyword rather than the `:=` operator.
## Restrictions
Constants are subject to the following restrictions:

View file

@ -9,7 +9,7 @@ class (and instance) definitions.
All definitions adhere to the following syntax:
```
[export] <definition type> <name> <description> is <body>
[export] <definition type> <name> <description> <body>
```
Each definition type ultimately controls the description and body. All

View file

@ -5,11 +5,17 @@ Enumerations are sum types.
## Example: The Option Type
```
enum Option[A] is
record Some[A] is (value: A)
given A
enum Option
given A
record Some (value: A)
object None
end enum
fn some[A]: (a: A) => Some[A] is a => Some(a)
given A
fn some: (a: A) => Some[A]
a => Some (a)
end fn
```
## Example: The Either Type
@ -17,10 +23,19 @@ fn some[A]: (a: A) => Some[A] is a => Some(a)
TODO: Describe import behavior! Does importing Either import Left/Right?
```
enum Either[L, R] is
record Left[L] is { value: L }
record Right[R] is { value: R }
given L, R
enum Either
given L
record Left (value: L)
fn left[L]: (left: L) => Either[L, Nothing] is l => Left { l }
fn right[R]: (right: R) => Either[Nothing, R] is r => Right { r }
given R
record Right (value: R)
given L
fn left: (left: L) => Either<L, Nothing> := l => Left(l)
end fn
given R
fn right: (right: R) => Either<Nothing, R> := Right(r)
end fn
```

15
examples.md Normal file
View file

@ -0,0 +1,15 @@
# Examples
## Hello, World!
```
namespace example;
fn exit_success: () => ExitCode
exit(0)
export fn main: (args: Array[String]) => Task[ExitCode]
println ("Hello, World!") -> exit_success
-- map (println ("Hi")) (exit_success)
```

View file

@ -1,34 +1,97 @@
# Functions
TODO: Scala syntax? Haskell syntax? Implications? How do we specify names for
parameters? Do we want to do that? How do function arguments, tuples, and
records all relate to one another? Are they all just the same? How do we talk
about curried functions? Is that supported? Is there some other mechanism?
TODO: This is all 100% up in the air right now.
## Syntax
```
fn example: () => Int32 is 42
example
example()
[given T1, T2, ... TN]
fn <name>: <input> => <output> :=
<body>
end fn
```
- `TN`: Type declaration (e.g. A :: Show)
- `name`: Follows the rules for [names](names.md)
- `input`: One or more named tuples ([records](records.md)).
- `output`: Some type.
- `body`: Function definition.
Note that `<input> => <output>` is the type of a function.
## Function Definitions
Function definitions are a series of expressions, where the value of the last
expression is returned.
```
fn example: (x: Int32, y: Int32) => Int32
let xx := x + 1
let yy := y + 1
xx * yy
end fn
```
## Calling Functions
Calling a function involves passing that function the tuples it needs.
```
given A :: Show
fn example: (a: A) => String
show(a)
end fn
fn calling_a_function: () => Task[()]
let x := 1
let y := true
let z := "foo"
println(show(x) + show(y) + show(z))
end fn
```
### Calling with Tuples
```
fn example: (x: Int32, y: Int32: z: Int32) => Int32
x + y + z
end fn
let inputs := (10, 20, 30)
example inputs
```
```
fn example: String => Int32 is str => length(str)
example "foo"
example("foo")
fn example: (x: Int32, y: Int32)(z: Int32, w: Int32) => Int32
x + y + z + w
end fn
let in1 := (1, 2)
let in2 := (3, 4)
example in1 in2
example (1, 2) in2
example in1 (3, 4)
```
```
fn example: { x: Int32, y: Int32 } => Int32 is (x, y) => x + y
example 1 2
example(1, 2)
example { x: 1, y: 2 }
```
## Generic Functions
## Referencing Arguments
`@args` refers to function arguments.
- For a single parameter list, it refers to the record.
- For multiple parameter lists, it refers to a tuple containing the lists in
order.
## Lazy Arguments
The `lazy` keyword allows the expression providing the value to have evaluation
deferred until the value is _used_ in the function. If the value is not used,
the expression is never evaluated.
```
fn map[F[*], A, B]: (F[A]) => (A => B) => F[B] is
(fa) (f) => fa f
map(list)(x => x + 1)
fn foo: (lazy x: Int32) => Int32
x * 2
end fn
```
Note that this is equivalent to encoding a parameter as a synchronous effect and
evaluating it to value when needed.

33
infix-operators.md Normal file
View file

@ -0,0 +1,33 @@
# Infix Operators
Example of defining `->` to do `map` for any functor:
```
given F[*] :: Functor, A, B
infix -> (fa: F[A], f: (A) => B) => F[B] :=
map (fa) (f)
```
```
let xs: List[Int] := list(1, 2, 3)
let addOne := (x: Int32) => x + 1
-- [2, 3, 4]
let ys := xs -> addOne
-- [4, 5, 6]
let zs := xs -> addOne -> addOne -> addOne
-- note, in order precedence: ((xs -> addOne) -> addOne) -> addOne
```
## Precedence
In order precedence.
## Using Parentheses to Group
Infix operators for numeric operations are defined for tuples of size one.
```
(12 - 2) / 2
```

View file

@ -12,7 +12,6 @@ Names are UTF-8 strings. The following values are _excluded_:
- `=`
- `"` or `'`
- `[` or `]`
- `{` or `}`
- `(` or `)`
## Convention

View file

@ -5,7 +5,7 @@ records are just [tuples](tuples.md) with named fields. In many ways, the two
can be interchanged.
```
record Foo is (x: String, y: Int32)
record Foo (x: String, y: Int32)
```
Record fields are both _ordered_ and _named_.
@ -31,13 +31,13 @@ Records do _not_ need to be named.
Records may have generically typed data, and accept a type constructor:
```
record Foo[A, B] is (x: A, y: B)
record Foo[A, B] (x: A, y: B)
```
## Instantiating Records
```
record Foo is (x: String, y: Int32)
record Foo (x: String, y: Int32)
let foo1 := Foo("foo", 1)
let foo2 := Foo(x := "foo", y := 1)
@ -49,7 +49,7 @@ Copy syntax allows any record to be duplicated, with any fields explicitly
overridden by some value:
```
record Foo is (x: String, y: Int32)
record Foo (x: String, y: Int32)
let foo := Foo("foo", 1)
let bar := copy(foo)
@ -61,7 +61,7 @@ let baz := copy(foo, ("y": 2))
The `.` operator is used to access individual fields on a record.
```
record Foo is (x: String, y: Int32)
record Foo (x: String, y: Int32)
let foo := Foo("foo", 1)
let bar := foo.x
@ -78,7 +78,7 @@ let baz: Int32 := foo._2
Use the following record definition for this section:
```
record Foo is (x: String, y: Int32)
record Foo (x: String, y: Int32)
```
Tuples can be assigned from records.

View file

@ -24,4 +24,8 @@
- [Holes](holes.md)
- [Pattern Matching](pattern-matching.md)
- [Recursion](recursion.md)
- [Infix Operators](infix-operators.md)
- [Standard Library](standard-library.md)
- [Examples](examples.md)
- [Standard Types](standard-types.md)
- [Numeric Overflow](numeric-overflow.md)

View file

@ -11,6 +11,16 @@ let x := ()
let y := ("foo")
let z := ("foo", 1)
let w := ("foo", 1, true, 3.14)
let a: Int32 := unwrap(1)
```
Unwrapping a tuple of size one is just the identity function:
```
given A
fn unwrap: (a: A) => A
a
end fn
```
## Type of a Standard Tuple

View file

@ -26,13 +26,14 @@ Types may directly, at the top level, be defined in terms of some
[type constructor](#type-constructors):
```
type TupleList[A, B] is List[(A, B)]
given A, B
type TupleList := List[(A, B)]
```
Or in general terms:
```
type <type constructor> is <type definition>
type <type constructor> := <type definition>
```
### Type Constructors
@ -41,7 +42,8 @@ Type constructors essentially allow for types to be defined in terms of some set
of type inputs. Consider the prior example:
```
type TupleList[A, B] is List[(A, B)]
given A, B
type TupleList := List[(A, B)]
```
The `TupleList` type requires two type arguments, `A` and `B`, to be constructed
@ -52,16 +54,21 @@ as a concrete type. For example, `TupleList[String, Int32]` is a concrete type.
Type constructors in Ava may be higher order (e.g. not order 1) functions:
```
// Assume this exists
type List[A] is ???
fn map[A, B]: (List[A], (A) => B) => List[B]
given A
type List is ???
type class Functor[F[*]] is
fn map[A, B]: (F[A])((A) => B) => F[B]
given A, B
fn map_list: (List[A], (A) => B) => List[B]
given F[*]
type class Functor is
given A, B
fn map: (F[A])((A) => B) => F<B>
instance Functor[List] is
fn map[A, B]: (List[A])((A) => B) => List[B] is
(list)(f) => map(list, f)
given A, B
fn map: (List[A])((A) => B) => [B] :=
(list)(f) => map_list (list, f)
```
In this example, `Functor[F[*]]` is a type constructor which accepts a single