First dump of madness.
This commit is contained in:
commit
c7aa5e19a9
26 changed files with 674 additions and 0 deletions
12
.pre-commit-config.yaml
Normal file
12
.pre-commit-config.yaml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
|
rev: v4.5.0
|
||||||
|
hooks:
|
||||||
|
- id: end-of-file-fixer
|
||||||
|
- id: trailing-whitespace
|
||||||
|
- id: fix-byte-order-marker
|
||||||
|
- id: mixed-line-ending
|
||||||
|
args: ['--fix=lf']
|
||||||
|
description: Enforces using only 'LF' line endings.
|
||||||
|
- id: trailing-whitespace
|
13
README.md
Normal file
13
README.md
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# The Ava Programming Language
|
||||||
|
|
||||||
|
This repository is currently a research project. The project is to explore ideas
|
||||||
|
in programming language design by specifying _Ava_.
|
||||||
|
|
||||||
|
To start reading, please use the [Table of Contents](./table-of-contents.md)
|
||||||
|
|
||||||
|
## What is Ava?
|
||||||
|
|
||||||
|
Ava is a programming language research project that is in the design and
|
||||||
|
specification phase. There is no grammar, parser, compiler, or way to use any
|
||||||
|
Ava code. Ava is a way to get ideas out of my head, challenged, and further
|
||||||
|
explored.
|
30
constants.md
Normal file
30
constants.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# Constants
|
||||||
|
|
||||||
|
_Constants_ are definitions which provide a name and explicit type for some
|
||||||
|
[value](values.md). The `const` keyword (definition type) is used to define a
|
||||||
|
constant.
|
||||||
|
|
||||||
|
```
|
||||||
|
const weak_pi: Float64 is 3.14
|
||||||
|
const my_name: String is "Pat"
|
||||||
|
```
|
||||||
|
|
||||||
|
In general:
|
||||||
|
|
||||||
|
```
|
||||||
|
const <name>: <type> is <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:
|
||||||
|
|
||||||
|
- Constants MUST refer to a literal value.
|
||||||
|
- Constants MUST have an explicit type.
|
||||||
|
- Constants MAY refer to a record instance.
|
||||||
|
- Constants CANNOT require a type constructor.
|
||||||
|
- Constants CANNOT refer to functions.
|
||||||
|
- Constants CANNOT refer to expressions.
|
29
definitions.md
Normal file
29
definitions.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Definitions
|
||||||
|
|
||||||
|
_Definitions_ are Ava constructs that may live at the top level within some
|
||||||
|
namespace. [Functions](functions.md) in particular may _also_ live within type
|
||||||
|
class (and instance) definitions.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
All definitions adhere to the following syntax:
|
||||||
|
|
||||||
|
```
|
||||||
|
[export] <definition type> <name> <description> is <body>
|
||||||
|
```
|
||||||
|
|
||||||
|
Each definition type ultimately controls the description and body. All
|
||||||
|
definition names adhere to standard [Name](names.md) rules.
|
||||||
|
|
||||||
|
## Supported Definition Types
|
||||||
|
|
||||||
|
TODO: This whole document... can go away? Need inventory of keywords.
|
||||||
|
|
||||||
|
- [`const`](constants.md)
|
||||||
|
- [`record`](records.md)
|
||||||
|
- [`type`](types.md)
|
||||||
|
- [`alias`](type-aliases.md)
|
||||||
|
- [`class`](type-classes.md)
|
||||||
|
- [`instance`](type-classes.md#instances)
|
||||||
|
- [`enum`](enumerations.md)
|
||||||
|
- [`fn`](functions.md)
|
8
effects.md
Normal file
8
effects.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Effects
|
||||||
|
|
||||||
|
## The Effect Type
|
||||||
|
|
||||||
|
The type `IO[E, A]` represents an effect which will produce `A` when executed,
|
||||||
|
and may fail with an error of type `E`. There exists a type
|
||||||
|
`type Task[A] = IO[Nothing, A]` that represents effects that cannot fail with an
|
||||||
|
error.
|
26
enumerations.md
Normal file
26
enumerations.md
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Enumerations
|
||||||
|
|
||||||
|
Enumerations are sum types.
|
||||||
|
|
||||||
|
## Example: The Option Type
|
||||||
|
|
||||||
|
```
|
||||||
|
enum Option[A] is
|
||||||
|
record Some[A] is (value: A)
|
||||||
|
object None
|
||||||
|
|
||||||
|
fn some[A]: (a: A) => Some[A] is a => Some(a)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example: The Either Type
|
||||||
|
|
||||||
|
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 }
|
||||||
|
|
||||||
|
fn left[L]: (left: L) => Either[L, Nothing] is l => Left { l }
|
||||||
|
fn right[R]: (right: R) => Either[Nothing, R] is r => Right { r }
|
||||||
|
```
|
45
expressions.md
Normal file
45
expressions.md
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# Expressions
|
||||||
|
|
||||||
|
_Expressions_ are the basis of programming in Ava. An expression is some code
|
||||||
|
that will produce a _value_ when evaluated.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
Most non-[Definition](definitions.md) code is considered an expression.
|
||||||
|
Expressions include:
|
||||||
|
|
||||||
|
- Literals
|
||||||
|
- Variables
|
||||||
|
- Function Calls
|
||||||
|
- Control Expressions
|
||||||
|
|
||||||
|
In general, using a Literal or a Variable for an expression wraps that value in
|
||||||
|
a `pure` function that returns the value when evaluated.
|
||||||
|
|
||||||
|
## Control Expressions
|
||||||
|
|
||||||
|
### If Then
|
||||||
|
|
||||||
|
The `if/then` expression expects an expression that returns a _Boolean Value_.
|
||||||
|
That expression is evaluated. If it evaluates to `true`, the `then` expression
|
||||||
|
is evaluated. Otherwise the `else` expression is evaluated.
|
||||||
|
|
||||||
|
```
|
||||||
|
if <boolean expr> then <expr> else <expr>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Do Yield
|
||||||
|
|
||||||
|
TODO: This is incomplete
|
||||||
|
|
||||||
|
The `do/yield` expression allows for imperative composition of monadic
|
||||||
|
expressions.
|
||||||
|
|
||||||
|
```
|
||||||
|
do
|
||||||
|
x <- foo()
|
||||||
|
y <- bar()
|
||||||
|
_ <- baz()
|
||||||
|
yield
|
||||||
|
x + y
|
||||||
|
```
|
34
functions.md
Normal file
34
functions.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
```
|
||||||
|
fn example: () => Int32 is 42
|
||||||
|
example
|
||||||
|
example()
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
fn example: String => Int32 is str => length(str)
|
||||||
|
example "foo"
|
||||||
|
example("foo")
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
fn example: { x: Int32, y: Int32 } => Int32 is (x, y) => x + y
|
||||||
|
example 1 2
|
||||||
|
example(1, 2)
|
||||||
|
example { x: 1, y: 2 }
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
fn map[F[*], A, B]: (F[A]) => (A => B) => F[B] is
|
||||||
|
(fa) (f) => fa f
|
||||||
|
|
||||||
|
map(list)(x => x + 1)
|
||||||
|
```
|
58
general-syntax.md
Normal file
58
general-syntax.md
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
# General Syntax
|
||||||
|
|
||||||
|
## Type Binding
|
||||||
|
|
||||||
|
Some name may be bound to some type by using the `:` (colon) syntax.
|
||||||
|
|
||||||
|
```
|
||||||
|
name: Type
|
||||||
|
```
|
||||||
|
|
||||||
|
Type bindings are used for all such occurrences. This includes:
|
||||||
|
|
||||||
|
- [Defining Variables](variables.md)
|
||||||
|
- [Defining Records](records.md)
|
||||||
|
- [Defining Functions](functions.md)
|
||||||
|
|
||||||
|
## Value Binding
|
||||||
|
|
||||||
|
Some name may be bound to some value by using the `:=` syntax.
|
||||||
|
|
||||||
|
```
|
||||||
|
name := value
|
||||||
|
name: Type := value
|
||||||
|
```
|
||||||
|
|
||||||
|
Value bindings are used for all such occurrences. This includes:
|
||||||
|
|
||||||
|
- [Defining Variables](variables.md)
|
||||||
|
- [Instantiating Records](records.md)
|
||||||
|
|
||||||
|
## Comments
|
||||||
|
|
||||||
|
Comments are lines where the first non-whitespace characters are `--`. This was
|
||||||
|
selected for ease of typing paired with low visual noise.
|
||||||
|
|
||||||
|
```
|
||||||
|
-- this is a comment
|
||||||
|
-- this is another comment
|
||||||
|
let x := "foo" -- this will not compile, comments cannot be mixed with code
|
||||||
|
```
|
||||||
|
|
||||||
|
Ava does not support multi-line comments.
|
||||||
|
|
||||||
|
## Code Documentation
|
||||||
|
|
||||||
|
Code documentation is written using comments that both directly-precede certain
|
||||||
|
definitions and have 3 `-` characters:
|
||||||
|
|
||||||
|
```
|
||||||
|
--- This function does some foo as well as some bar.
|
||||||
|
--- @param x Documentation for the `x` parameter.
|
||||||
|
fn foo_bar: (x: String) => Int32
|
||||||
|
```
|
||||||
|
|
||||||
|
- Code documentation respects Markdown.
|
||||||
|
- TODO: Link syntax.
|
||||||
|
- TODO: Supported definitions (example for each)
|
||||||
|
- TODO: Parameter documentation
|
4
holes.md
Normal file
4
holes.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Holes
|
||||||
|
|
||||||
|
`???` is a hole that resolves to any type, used for development, cannot be used
|
||||||
|
at runtime at all (it blows up).
|
1
memory-management.md
Normal file
1
memory-management.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Memory Management
|
23
names.md
Normal file
23
names.md
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# Names
|
||||||
|
|
||||||
|
_Names_ are user-defined strings that name defined items. All names (variable
|
||||||
|
names, function names, etc.) follow the same rules.
|
||||||
|
|
||||||
|
Names are UTF-8 strings. The following values are _excluded_:
|
||||||
|
|
||||||
|
- Any reserved keyword
|
||||||
|
- Any whitespace character
|
||||||
|
- `.`
|
||||||
|
- `:`
|
||||||
|
- `=`
|
||||||
|
- `"` or `'`
|
||||||
|
- `[` or `]`
|
||||||
|
- `{` or `}`
|
||||||
|
- `(` or `)`
|
||||||
|
|
||||||
|
## Convention
|
||||||
|
|
||||||
|
- Variables use `lower_snake_case`
|
||||||
|
- Functions use `lower_snake_case`
|
||||||
|
- Generic Types use `UpperCamelCase` but prefer single letters such as `A`.
|
||||||
|
- Data Types, aliases, etc. use `UpperCamelCase`
|
76
namespaces.md
Normal file
76
namespaces.md
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
# Namespaces
|
||||||
|
|
||||||
|
_Namespaces_ are the primary organizational unit of Ava. Every Ava file _must_
|
||||||
|
define a namespace. The namespace is ALWAYS the first line of the file.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
Each namespace is an ordered, delimited, list of [names](names.md). Each name is
|
||||||
|
separated by the `.` character.
|
||||||
|
|
||||||
|
```
|
||||||
|
<name>[.<name>]*
|
||||||
|
```
|
||||||
|
|
||||||
|
- At least one name MUST be specified.
|
||||||
|
- CANNOT contain more than one `.` character in a row.
|
||||||
|
- CANNOT begin with `.` character.
|
||||||
|
- CANNOT end with `.` character.
|
||||||
|
- CANNOT use a [Reserved Name](#reserved-names).
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
- `foo`
|
||||||
|
- `foo.bar.baz`
|
||||||
|
- `language.v0`
|
||||||
|
- `collections.v0`
|
||||||
|
|
||||||
|
## Reserved Names
|
||||||
|
|
||||||
|
Any namespaces provided with a particular Ava distribution are considered
|
||||||
|
_reserved_. This means that, for example, the following namespaces cannot be
|
||||||
|
used:
|
||||||
|
|
||||||
|
- `language`
|
||||||
|
- `collections`
|
||||||
|
|
||||||
|
## Language Namespace
|
||||||
|
|
||||||
|
The `language` namespace is automatically imported into every Ava file.
|
||||||
|
|
||||||
|
## Exports
|
||||||
|
|
||||||
|
Each namespace MAY _export_ defintions using the `export` keyword. If some
|
||||||
|
definition is exported, it may be [imported](#imports) into another namespace.
|
||||||
|
Definitions are NOT exported by default -- it is an opt-in process. As noted in
|
||||||
|
the [Definitions](definitions.md) documentation, the `export` keyword may be
|
||||||
|
used at the beginning of _any_ definition.
|
||||||
|
|
||||||
|
## Imports
|
||||||
|
|
||||||
|
Imports immediately follow the namespace definition in each file. Each file may
|
||||||
|
have zero or more imports. Imports bring definitions from another namespace into
|
||||||
|
scope.
|
||||||
|
|
||||||
|
### Syntax
|
||||||
|
|
||||||
|
Each import is a single, fully-qualified name. Imported names MAY be mapped to
|
||||||
|
some alternative name. An import may refer to a specific namespace or it may
|
||||||
|
refer to some specific definition within a namespace.
|
||||||
|
|
||||||
|
TODO: Account for type classes. How can we easily import instances? One option
|
||||||
|
is to NOT do this. Ever. Just resolve EVERY possible `instance` during
|
||||||
|
compilation and make them available within the scope of the program. Global.
|
||||||
|
Very strict one-instance-per-thing side-effect, but could be useful.
|
||||||
|
|
||||||
|
```
|
||||||
|
import <namespace>[.<definition name>] [as <name>]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
```
|
||||||
|
import collections.NonEmptyList as NEL
|
||||||
|
import collections.Queue
|
||||||
|
import collections
|
||||||
|
```
|
29
pattern-matching.md
Normal file
29
pattern-matching.md
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
# Pattern Matching
|
||||||
|
|
||||||
|
TODO: This needs just more description and examples and pressure testing.
|
||||||
|
|
||||||
|
Ava supports pattern matching and value destructuring.
|
||||||
|
|
||||||
|
## The Match Expression
|
||||||
|
|
||||||
|
```
|
||||||
|
match <expr>
|
||||||
|
case <pattern> => <expr>
|
||||||
|
case <pattern> => <expr>
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## The Default Case
|
||||||
|
|
||||||
|
The _default case_, `_`, is used to catch all unmatched cases. This can be used
|
||||||
|
to only match a partial set of possible values:
|
||||||
|
|
||||||
|
TODO: WIP gotta figure out functions.
|
||||||
|
|
||||||
|
```
|
||||||
|
fn example: String => Int32 is
|
||||||
|
str => match str
|
||||||
|
case "foo" => 1
|
||||||
|
case "bar" => 2
|
||||||
|
case _ => 3
|
||||||
|
```
|
101
records.md
Normal file
101
records.md
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
# Records
|
||||||
|
|
||||||
|
Records may be defined. Each record contains one or more named fields. Note that
|
||||||
|
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 fields are both _ordered_ and _named_.
|
||||||
|
|
||||||
|
- [Anonymous Records](#anonymous-records)
|
||||||
|
- [Generic Records](#generic-records)
|
||||||
|
- [Instantiating Records](#instantiating-records)
|
||||||
|
- [Copying Data](#copying-data)
|
||||||
|
- [Accessing Record Data](#accessing-record-data)
|
||||||
|
- [Tuple Interactions](#tuple-interactions)
|
||||||
|
- [Destructuring Records](#destructuring-records)
|
||||||
|
|
||||||
|
## Anonymous Records
|
||||||
|
|
||||||
|
Records do _not_ need to be named.
|
||||||
|
|
||||||
|
```
|
||||||
|
(x: String, y: String, z: String)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generic Records
|
||||||
|
|
||||||
|
Records may have generically typed data, and accept a type constructor:
|
||||||
|
|
||||||
|
```
|
||||||
|
record Foo[A, B] is (x: A, y: B)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Instantiating Records
|
||||||
|
|
||||||
|
```
|
||||||
|
record Foo is (x: String, y: Int32)
|
||||||
|
|
||||||
|
let foo1 := Foo("foo", 1)
|
||||||
|
let foo2 := Foo(x := "foo", y := 1)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Copying Data
|
||||||
|
|
||||||
|
Copy syntax allows any record to be duplicated, with any fields explicitly
|
||||||
|
overridden by some value:
|
||||||
|
|
||||||
|
```
|
||||||
|
record Foo is (x: String, y: Int32)
|
||||||
|
|
||||||
|
let foo := Foo("foo", 1)
|
||||||
|
let bar := copy(foo)
|
||||||
|
let baz := copy(foo, ("y": 2))
|
||||||
|
```
|
||||||
|
|
||||||
|
## Accessing Record Data
|
||||||
|
|
||||||
|
The `.` operator is used to access individual fields on a record.
|
||||||
|
|
||||||
|
```
|
||||||
|
record Foo is (x: String, y: Int32)
|
||||||
|
|
||||||
|
let foo := Foo("foo", 1)
|
||||||
|
let bar := foo.x
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that because records are just tuples, tuple syntax continues to work:
|
||||||
|
|
||||||
|
```
|
||||||
|
let baz: Int32 := foo._2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tuple Interactions
|
||||||
|
|
||||||
|
Use the following record definition for this section:
|
||||||
|
|
||||||
|
```
|
||||||
|
record Foo is (x: String, y: Int32)
|
||||||
|
```
|
||||||
|
|
||||||
|
Tuples can be assigned from records.
|
||||||
|
|
||||||
|
```
|
||||||
|
let foo := Foo("foo", 1)
|
||||||
|
let some_tuple: (String, Int32) := foo
|
||||||
|
```
|
||||||
|
|
||||||
|
Records can be assigned from tuples.
|
||||||
|
|
||||||
|
```
|
||||||
|
let some_tuple := ("foo", 1)
|
||||||
|
let foo: Foo := some_tuple
|
||||||
|
```
|
||||||
|
|
||||||
|
## Destructuring Records
|
||||||
|
|
||||||
|
Records can be _destructured_ via [pattern matching](pattern-matching.md)
|
||||||
|
capabilities. This can take two possible forms.
|
3
recursion.md
Normal file
3
recursion.md
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
# Recursion
|
||||||
|
|
||||||
|
TCO is supported.
|
5
standard-library.md
Normal file
5
standard-library.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
# Standard Library
|
||||||
|
|
||||||
|
Things like supporting different standard functions, type class list, etc.
|
||||||
|
|
||||||
|
What about collections?
|
1
strings.md
Normal file
1
strings.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Strings
|
27
table-of-contents.md
Normal file
27
table-of-contents.md
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
# Table of Contents
|
||||||
|
|
||||||
|
- [Names](names.md)
|
||||||
|
- [Namespaces](namespaces.md)
|
||||||
|
- [Exports](namespaces.md#exports)
|
||||||
|
- [Imports](namespaces.md#imports)
|
||||||
|
- [Definitions](definitions.md)
|
||||||
|
- [General Syntax](general-syntax.md)
|
||||||
|
- [Expressions](expressions.md)
|
||||||
|
- [Values](values.md)
|
||||||
|
- [Constants](constants.md)
|
||||||
|
- [Variables](variables.md)
|
||||||
|
- [Effects](effects.md)
|
||||||
|
- [Records](records.md)
|
||||||
|
- [Types](types.md)
|
||||||
|
- [Type Aliases](type-aliases.md)
|
||||||
|
- [Type Classes](type-classes.md)
|
||||||
|
- [Enumerations](enumerations.md)
|
||||||
|
- [Type Unions](type-unions.md)
|
||||||
|
- [Functions](functions.md)
|
||||||
|
- [Strings](strings.md)
|
||||||
|
- [Tuples](tuples.md)
|
||||||
|
- [Memory Management](memory-management.md)
|
||||||
|
- [Holes](holes.md)
|
||||||
|
- [Pattern Matching](pattern-matching.md)
|
||||||
|
- [Recursion](recursion.md)
|
||||||
|
- [Standard Library](standard-library.md)
|
61
tuples.md
Normal file
61
tuples.md
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
# Tuples
|
||||||
|
|
||||||
|
Tuples are heterogeneous, fixed-size, collections of values. Tuples contain 0 to
|
||||||
|
`N` values, where `N` is unbounded. Tuples are similar to [Records](records.md),
|
||||||
|
but records have named parameters.
|
||||||
|
|
||||||
|
## Syntax
|
||||||
|
|
||||||
|
```
|
||||||
|
let x := ()
|
||||||
|
let y := ("foo")
|
||||||
|
let z := ("foo", 1)
|
||||||
|
let w := ("foo", 1, true, 3.14)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Type of a Standard Tuple
|
||||||
|
|
||||||
|
Consider the tuple `("foo", 1, true, 3.14)`. It has type
|
||||||
|
`(String, Int32, Boolean, Float64)`.
|
||||||
|
|
||||||
|
## The Empty Tuple
|
||||||
|
|
||||||
|
The type `()` has a single possible value, `()`. This is the empty tuple. It is
|
||||||
|
typically used as a token to indicate side-effects with no other useful output.
|
||||||
|
|
||||||
|
## Accessing Tuple Members
|
||||||
|
|
||||||
|
Each tuple member is _indexed_ and can be directly accessed via a property of
|
||||||
|
that index:
|
||||||
|
|
||||||
|
```
|
||||||
|
let w := ("foo", 1, true)
|
||||||
|
let x := w._1
|
||||||
|
let y := w._2
|
||||||
|
let z := w._3
|
||||||
|
```
|
||||||
|
|
||||||
|
## Destructuring Tuples
|
||||||
|
|
||||||
|
Tuples can be _destructured_ via [pattern matching](pattern-matching.md)
|
||||||
|
capabilities. This can take two possible forms.
|
||||||
|
|
||||||
|
### Destructured Binding
|
||||||
|
|
||||||
|
Tuples may be destructured at the point of binding.
|
||||||
|
|
||||||
|
```
|
||||||
|
let w := ("foo", 1, true)
|
||||||
|
let (x, y, z) := w
|
||||||
|
```
|
||||||
|
|
||||||
|
### Destructured Match Case
|
||||||
|
|
||||||
|
```
|
||||||
|
let w := ("foo", 1, true)
|
||||||
|
|
||||||
|
let z :=
|
||||||
|
match w
|
||||||
|
case ("foo", _, x) => x
|
||||||
|
case _ => false
|
||||||
|
```
|
1
type-aliases.md
Normal file
1
type-aliases.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Type Aliases
|
1
type-classes.md
Normal file
1
type-classes.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Type Classes
|
8
type-unions.md
Normal file
8
type-unions.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Type Unions
|
||||||
|
|
||||||
|
TODO: Explore. What syntax is better? `|` seems better.
|
||||||
|
|
||||||
|
```
|
||||||
|
type Foo = String | Int32
|
||||||
|
type Bar = Boolean or String or Int32
|
||||||
|
```
|
69
types.md
Normal file
69
types.md
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
# Types
|
||||||
|
|
||||||
|
- [The Ava Type System](#the-ava-type-system)
|
||||||
|
- [The Nothing Type](#the-nothing-type)
|
||||||
|
- [Type Definitions](#type-definitions)
|
||||||
|
- [Type Constructors](#type-constructors)
|
||||||
|
- [Higher Kinded Types](#higher-kinded-types)
|
||||||
|
|
||||||
|
## The Ava Type System
|
||||||
|
|
||||||
|
Ava is based on a static type system with support for higher-kinded types. Ava
|
||||||
|
does not support inheritence. Ava _does_ support sum types
|
||||||
|
([Enumerations](enumerations.md)) and _does_ support
|
||||||
|
[type classes](type-classes.md).
|
||||||
|
|
||||||
|
## The Nothing Type
|
||||||
|
|
||||||
|
The special type, `Nothing`, cannot be instantiated. It can be used to describe
|
||||||
|
cases that cannot be expressed. For example, `Either[Nothing, String]` cannot
|
||||||
|
ever be a `Left`. `Nothing` can be used to satisfy any type requirement. For
|
||||||
|
example, `Either[Nothing, String]` satisfies `Either[Int32, String]`.
|
||||||
|
|
||||||
|
## Type Definitions
|
||||||
|
|
||||||
|
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)]
|
||||||
|
```
|
||||||
|
|
||||||
|
Or in general terms:
|
||||||
|
|
||||||
|
```
|
||||||
|
type <type constructor> is <type definition>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Type Constructors
|
||||||
|
|
||||||
|
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)]
|
||||||
|
```
|
||||||
|
|
||||||
|
The `TupleList` type requires two type arguments, `A` and `B`, to be constructed
|
||||||
|
as a concrete type. For example, `TupleList[String, Int32]` is a concrete type.
|
||||||
|
|
||||||
|
## Higher Kinded Types
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
type class Functor[F[*]] is
|
||||||
|
fn map[A, B]: (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)
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example, `Functor[F[*]]` is a type constructor which accepts a single
|
||||||
|
type argument. That type argument is a type constructor that accepts a single
|
||||||
|
concrete (order 0) type argument.
|
1
values.md
Normal file
1
values.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Values
|
8
variables.md
Normal file
8
variables.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
# Variables
|
||||||
|
|
||||||
|
- [Immutable Values](#immutable-values)
|
||||||
|
- [Mutable Values](#mutable-values)
|
||||||
|
|
||||||
|
## Variable Names
|
||||||
|
|
||||||
|
Please refer to [Names](names.md).
|
Loading…
Add table
Reference in a new issue