Continuing to toss ideas around and work on different parts of the base design.
This commit is contained in:
parent
5854408466
commit
218647484d
11 changed files with 197 additions and 54 deletions
|
@ -5,19 +5,16 @@ _Constants_ are definitions which provide a name and explicit type for some
|
||||||
constant.
|
constant.
|
||||||
|
|
||||||
```
|
```
|
||||||
const weak_pi: Float64 is 3.14
|
const weak_pi: Float64 := 3.14
|
||||||
const my_name: String is "Pat"
|
const my_name: String := "Pat"
|
||||||
```
|
```
|
||||||
|
|
||||||
In general:
|
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
|
## Restrictions
|
||||||
|
|
||||||
Constants are subject to the following restrictions:
|
Constants are subject to the following restrictions:
|
||||||
|
|
|
@ -9,7 +9,7 @@ class (and instance) definitions.
|
||||||
All definitions adhere to the following syntax:
|
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
|
Each definition type ultimately controls the description and body. All
|
||||||
|
|
|
@ -5,11 +5,17 @@ Enumerations are sum types.
|
||||||
## Example: The Option Type
|
## Example: The Option Type
|
||||||
|
|
||||||
```
|
```
|
||||||
enum Option[A] is
|
given A
|
||||||
record Some[A] is (value: A)
|
enum Option
|
||||||
|
given A
|
||||||
|
record Some (value: A)
|
||||||
object None
|
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
|
## 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?
|
TODO: Describe import behavior! Does importing Either import Left/Right?
|
||||||
|
|
||||||
```
|
```
|
||||||
enum Either[L, R] is
|
given L, R
|
||||||
record Left[L] is { value: L }
|
enum Either
|
||||||
record Right[R] is { value: R }
|
given L
|
||||||
|
record Left (value: L)
|
||||||
|
|
||||||
fn left[L]: (left: L) => Either[L, Nothing] is l => Left { l }
|
given R
|
||||||
fn right[R]: (right: R) => Either[Nothing, R] is r => Right { 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
15
examples.md
Normal 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)
|
||||||
|
```
|
107
functions.md
107
functions.md
|
@ -1,34 +1,97 @@
|
||||||
# Functions
|
# Functions
|
||||||
|
|
||||||
TODO: Scala syntax? Haskell syntax? Implications? How do we specify names for
|
## Syntax
|
||||||
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.
|
|
||||||
|
|
||||||
```
|
```
|
||||||
fn example: () => Int32 is 42
|
[given T1, T2, ... TN]
|
||||||
example
|
fn <name>: <input> => <output> :=
|
||||||
example()
|
<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)
|
fn example: (x: Int32, y: Int32)(z: Int32, w: Int32) => Int32
|
||||||
example "foo"
|
x + y + z + w
|
||||||
example("foo")
|
end fn
|
||||||
|
|
||||||
|
let in1 := (1, 2)
|
||||||
|
let in2 := (3, 4)
|
||||||
|
example in1 in2
|
||||||
|
example (1, 2) in2
|
||||||
|
example in1 (3, 4)
|
||||||
```
|
```
|
||||||
|
|
||||||
```
|
## Generic Functions
|
||||||
fn example: { x: Int32, y: Int32 } => Int32 is (x, y) => x + y
|
|
||||||
example 1 2
|
## Referencing Arguments
|
||||||
example(1, 2)
|
|
||||||
example { x: 1, y: 2 }
|
`@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
|
fn foo: (lazy x: Int32) => Int32
|
||||||
(fa) (f) => fa f
|
x * 2
|
||||||
|
end fn
|
||||||
map(list)(x => x + 1)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
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
33
infix-operators.md
Normal 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
|
||||||
|
```
|
1
names.md
1
names.md
|
@ -12,7 +12,6 @@ Names are UTF-8 strings. The following values are _excluded_:
|
||||||
- `=`
|
- `=`
|
||||||
- `"` or `'`
|
- `"` or `'`
|
||||||
- `[` or `]`
|
- `[` or `]`
|
||||||
- `{` or `}`
|
|
||||||
- `(` or `)`
|
- `(` or `)`
|
||||||
|
|
||||||
## Convention
|
## Convention
|
||||||
|
|
12
records.md
12
records.md
|
@ -5,7 +5,7 @@ records are just [tuples](tuples.md) with named fields. In many ways, the two
|
||||||
can be interchanged.
|
can be interchanged.
|
||||||
|
|
||||||
```
|
```
|
||||||
record Foo is (x: String, y: Int32)
|
record Foo (x: String, y: Int32)
|
||||||
```
|
```
|
||||||
|
|
||||||
Record fields are both _ordered_ and _named_.
|
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:
|
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
|
## Instantiating Records
|
||||||
|
|
||||||
```
|
```
|
||||||
record Foo is (x: String, y: Int32)
|
record Foo (x: String, y: Int32)
|
||||||
|
|
||||||
let foo1 := Foo("foo", 1)
|
let foo1 := Foo("foo", 1)
|
||||||
let foo2 := Foo(x := "foo", y := 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:
|
overridden by some value:
|
||||||
|
|
||||||
```
|
```
|
||||||
record Foo is (x: String, y: Int32)
|
record Foo (x: String, y: Int32)
|
||||||
|
|
||||||
let foo := Foo("foo", 1)
|
let foo := Foo("foo", 1)
|
||||||
let bar := copy(foo)
|
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.
|
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 foo := Foo("foo", 1)
|
||||||
let bar := foo.x
|
let bar := foo.x
|
||||||
|
@ -78,7 +78,7 @@ let baz: Int32 := foo._2
|
||||||
Use the following record definition for this section:
|
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.
|
Tuples can be assigned from records.
|
||||||
|
|
|
@ -24,4 +24,8 @@
|
||||||
- [Holes](holes.md)
|
- [Holes](holes.md)
|
||||||
- [Pattern Matching](pattern-matching.md)
|
- [Pattern Matching](pattern-matching.md)
|
||||||
- [Recursion](recursion.md)
|
- [Recursion](recursion.md)
|
||||||
|
- [Infix Operators](infix-operators.md)
|
||||||
- [Standard Library](standard-library.md)
|
- [Standard Library](standard-library.md)
|
||||||
|
- [Examples](examples.md)
|
||||||
|
- [Standard Types](standard-types.md)
|
||||||
|
- [Numeric Overflow](numeric-overflow.md)
|
||||||
|
|
10
tuples.md
10
tuples.md
|
@ -11,6 +11,16 @@ let x := ()
|
||||||
let y := ("foo")
|
let y := ("foo")
|
||||||
let z := ("foo", 1)
|
let z := ("foo", 1)
|
||||||
let w := ("foo", 1, true, 3.14)
|
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
|
## Type of a Standard Tuple
|
||||||
|
|
27
types.md
27
types.md
|
@ -26,13 +26,14 @@ Types may directly, at the top level, be defined in terms of some
|
||||||
[type constructor](#type-constructors):
|
[type constructor](#type-constructors):
|
||||||
|
|
||||||
```
|
```
|
||||||
type TupleList[A, B] is List[(A, B)]
|
given A, B
|
||||||
|
type TupleList := List[(A, B)]
|
||||||
```
|
```
|
||||||
|
|
||||||
Or in general terms:
|
Or in general terms:
|
||||||
|
|
||||||
```
|
```
|
||||||
type <type constructor> is <type definition>
|
type <type constructor> := <type definition>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Type Constructors
|
### 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:
|
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
|
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:
|
Type constructors in Ava may be higher order (e.g. not order 1) functions:
|
||||||
|
|
||||||
```
|
```
|
||||||
// Assume this exists
|
given A
|
||||||
type List[A] is ???
|
type List is ???
|
||||||
fn map[A, B]: (List[A], (A) => B) => List[B]
|
|
||||||
|
|
||||||
type class Functor[F[*]] is
|
given A, B
|
||||||
fn map[A, B]: (F[A])((A) => B) => F[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
|
instance Functor[List] is
|
||||||
fn map[A, B]: (List[A])((A) => B) => List[B] is
|
given A, B
|
||||||
(list)(f) => map(list, f)
|
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
|
In this example, `Functor[F[*]]` is a type constructor which accepts a single
|
||||||
|
|
Loading…
Add table
Reference in a new issue