Home

Awesome

Sparcl: A Language for Partially-Invertible Computation

This is an implementation of a system presented in the following paper.

Kazutaka Matsuda and Meng Wang: Sparcl: A Language for Partially-Invertible Computation, ICFP 2020. 

How to Use

First, we need to build the system. We use stack for building, so please install stack by following the instruction found in the link. Once stack has been installed, then type as below to build the system.

$ stack build

The command may take some time as it builds all required packages including a version of GHC.

Then, we can start the read-eval-print loop by:

$ stack exec sparcl-exe

After invoking the executable, one will see that the system shows the following prompt.

Sparcl> 

One thing users can do is to input an expression to examine its evaluation results.

Sparcl> 1 + 2 
3 

Also, users can ask the inferred type of an expression.

Sparcl> :type \x -> x 
...
forall a b. b # a -> b 

We have some examples under ./Examples in this distribution. Seeing ./Examples/T1.sparcl would be useful for knowing the syntax of Sparcl. The loading can be done by the command :load.

Sparcl> :load Examples/T1.sparcl 
...

Then, you can use types and functions defined in the file.

Sparcl> fwd (add (S Z)) (S (S Z))
...
S (S (S Z))
Sparcl> bwd (add (S Z)) (S (S (S Z)))
...
S (S Z)

Typing :help and then enter will show the help as below.

Sparcl> :help
:quit
    Quit REPL.
:load FILEPATH
    Load a program.
:reload
    Reload the last program.
:help
    Show this help.
:type EXP
    Print the expression's type.

Currently, there is no batch execution mode. Invoking the executable with a file name is equivalent to invoking it without a file name and executing command :load.

Synopses of Examples

There are roughly two sorts of examples, focusing on linear typing and partial invertibility respectively.

Examples concerning Linear Typing

App*.sparcl, F.sparcl and GV_func.sparcl are used in the experiments in Kazutaka Matsuda: "Modular Inference of Linear Types for Multiplicity-Annotated Arrows". ESOP 2020.

Examples concerning Partially Invertible Computation

In the following, section numbers refer to those in the paper.

Notable Differences from the Paper (ICFP 2020)

Rough Explanation of Syntax

Here, we briefly explain the syntax of Sparcl. This explanation is not a complete documentation, but only to help understand the examples.

A program consists of type or function definitions. A type declaration can be datatype declarations, or type synonym declarations.

data T a1 ... an = C Ty1 ... Tym | ... | C' Ty1' ... Tyk
type T a1 ... an = T Ty1 ... Tym

Their syntax is a similar to Haskell's one. Unlike Haskell, there is no partial applications of types and each type variable must range over types or multiplicities. Currently, the system does not have kind-checking. So, it may accept some ill-formed type declarations.

We also allow GADTs, but use a different syntax from Haskell's. See, GV_func.sparcl for an example.

Types in Sparcl include following ones.

Sparcl's type system is rank 1 and polymorphic types can appear in limited positions, namely outermost positions of signature declarations (i.e., Ty of sig f : Ty below).

A function definition has the form of:

sig f : Ty 
def f p1 ... pn = e1 with e1' 
    | ...
    | q1 ... qn = ek with e2' 
    

Here, the with part is required only if patterns of a branch contain an invertible patterns rev p. Branches with invertible patterns will be converted to invertible cases internally, while there is no such special case expression in the surface language. The sig declaration is optional.

Other than invertible patterns rev p, patterns can also be:

Invertible patterns cannot be nested. Value patterns and guards are not supported yet.

Expressions are rather standard except invertible constructors rev C. We can use:

Notice that case expressions require closing delimiters.

Local definitions are supported via let ... in e and where ... end. The former is an expression while the latter can only appear after a branch (such as def f x = y where def y = 1 end and case 1 of x -> y where def y = 1 end end).

Publications

Known Issues