duet/README.md

116 lines
3.1 KiB
Markdown
Raw Normal View History

2017-04-19 12:16:50 +03:00
# Duet
2017-04-18 12:01:37 +03:00
2019-11-15 18:59:20 +03:00
A tiny language, a subset of Haskell (with type classes) aimed at aiding teachers teach Haskell
2017-05-08 12:45:59 +03:00
2019-11-15 18:24:28 +03:00
## Usage
2018-05-24 14:32:08 +03:00
2019-11-15 18:24:28 +03:00
This comes as a library and as a program capable of running Duet programs.
2018-05-24 14:32:08 +03:00
2017-05-08 12:48:18 +03:00
```
2019-11-15 18:24:28 +03:00
$ duet --help
Duet interpreter
2017-05-08 12:52:20 +03:00
2019-11-15 18:24:28 +03:00
Usage: duet [--version] [--help] COMMAND
This is the interpreter for the Duet mini-Haskell educational language
2017-05-08 12:52:20 +03:00
2019-11-15 18:24:28 +03:00
Available options:
--version Show version
--help Show this help text
2017-05-08 12:52:20 +03:00
2019-11-15 18:24:28 +03:00
Available commands:
run Run the given program source
2017-05-08 12:52:20 +03:00
```
2019-11-15 18:32:21 +03:00
2019-11-15 18:55:03 +03:00
## Run
The help for this command:
```
Usage: duet run FILEPATH [--main NAME] [--concise] [-n|--steps steps]
Run the given program source
Available options:
-h,--help Show this help text
FILEPATH The .hs file to interpret
--main NAME The main value to run
--concise Concise view
2019-11-15 18:56:16 +03:00
-n,--steps steps Maximum number of steps to run (default: 100)
2019-11-15 18:55:03 +03:00
```
Running code in Duet literally performs one substitution step at
time. For example, evaluating `(\x -> x + 5) (2 * 3)`, we get:
``` haskell
[1]
(\x -> x + 5) (2 * 3)
[2]
(2 * 3) + 5
[3]
6 + 5
[4]
11
```
Note that this demonstrates basic argument application and non-strictness.
2019-11-15 18:47:33 +03:00
Example `integers.hs`:
2019-11-15 18:32:21 +03:00
```haskell
main = 3 + ((2 + -3) - 3)
```
Output for this program:
``` haskell
$ duet run examples/integers.hs
[1]
3 + ((2 + -3) - 3)
[2]
3 + (-1 - 3)
[3]
3 + -4
[4]
-1
```
2019-11-15 18:44:50 +03:00
## Differences from Haskell
See also the next section for a complete example using all the
available syntax.
2019-11-15 18:57:46 +03:00
* Duet is non-strict, but is not lazy. There is no sharing and no
thunks.
* No `module` or `import` module system whatsoever.
2019-11-15 18:44:50 +03:00
* No `let` syntax, no parameters in definitions e.g. `f x = ..` you
2019-11-15 18:49:26 +03:00
must use a lambda. Representing `let` in the stepper presents a
design challenge not currently met.
2019-11-15 18:44:50 +03:00
* Kinds `*` are written `Type`: e.g. `class Functor (f :: Type -> Type)`.
* Kind inference is not implemented, so if you want a kind other than
`Type` (aka `*` in Haskell), you have to put a kind signature on the
type variable.
* Indentation is stricter, a case's alts must be at a column larger
than the `case`.
* Infix operators are stricter: an infix operator must have spaces
around it. You **cannot** have more than one operator without
parentheses, therefore operator precedence does not come into play
2019-11-15 18:51:53 +03:00
in Duet (this is intentional). This also permits you to write `-5`
without worrying about where it rests.
2019-11-15 18:44:50 +03:00
* Superclasses are not supported.
* Operator definitions are not supported.
* There is only `Integer` and `Rational` number types: they are
written as `1` or `1.0`.
2019-11-15 18:47:07 +03:00
* Any `_` or `_foo` means "hole" and the interpreter does not touch
them, it continues performing rewrites without caring. This is good
for teaching.
2019-11-15 18:44:50 +03:00
* There is no standard `Prelude`. The only defined base types are:
* String
* Char
* Integer
* Rational
* Bool
* You don't need a `Show` instance to inspect values; the interpreter
2019-11-15 18:49:26 +03:00
shows them as they are, including lambdas.
2019-11-15 18:44:50 +03:00
2019-11-15 18:50:55 +03:00
View `examples/syntax-buffet.hs` for an example featuring all the
syntax supported in Duet.