Subskell is a small functional language with the following features:
- Types
- Integers
- Booleans
- First class functions
- Comments
- Currying
- Laziness (call by name)
- Static scoping
- Type inference
- Optional type hints
- Let polymorphism
dune exec subskell run <file>
to evaluate Subskell code in a file.
dune exec subskell annotate <file>
to view the source code with type hints generated by the type inference algorithm.
dune test
to run the provided tests.
The pieces of code below may also be found in examples/
.
The code below illustrates the use of features such as comments, type hints, recursion and currying.
let n : int = 10 -- n-th power of 2 to compute
-- compute n^m
in let power : int -> int -> int =
fun n -> fun m -> if m = 0 then 1 else n*power n (m-1)
-- compute 2^m
in let powersof2 = power 2
in powersof2 n
The example below demonstrates let polymorphism.
let id = fun x -> x
in let eq = (=)
in let eqtrue = (=) true
in let eqzero = (=) 0
in if eqtrue (id true) && eqzero (id 0)
then id 1337
else id 420
The above is equal to:
let id : 'a. 'a -> 'a = fun x -> x
in let eq : 'a. 'a -> 'a -> bool = (=)
in let eqtrue : bool -> bool = (=) true
in let eqzero : int -> bool = (=) 0
in if eqtrue (id true) && eqzero (id 0)
then id 1337
else id 420
Type schemes must be marked explicitly.
The example below illustrates what happens when type schemes are omitted.
let id : 'a -> 'a = fun x -> x
in let eq: 'a -> 'a -> bool = (=)
in let five = id 5
in eq
Using the annotate
feature on the code above yields us the following output:
Annotated source code of examples/typeschemewithout.sml:
let id : 'a -> 'a = fun x -> x
in let eq : 'a -> 'a -> bool = (=)
in let five : int = id (5)
in eq
Inferred type: int -> int -> bool
eq
shares the type variable 'a
used in the type hint of id
. Then, thanks to the definition of five
, we infer 'a = int
.
The may not be what the programmer intended.
The below illustrates the previous example with type schemes instead of type variables.
let id : 'a. 'a -> 'a = fun x -> x
in let eq: 'a. 'a -> 'a -> bool = (=)
in let five = id 5
in eq
Running annotate
on the above:
Annotated source code of examples/typescheme.sml:
let id : 'a. 'a -> 'a = fun x -> x
in let eq : 'a. 'a -> 'a -> bool = (=)
in let five : int = id (5)
in eq
Inferred type: 'h -> 'h -> bool
In this case, id
and eq
may be instantiated for any type 'a
.