• Stars
    star
    180
  • Rank 213,097 (Top 5 %)
  • Language
    Haskell
  • License
    MIT License
  • Created over 7 years ago
  • Updated 5 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Elsa is a lambda calculus evaluator

ELSA

elsa is a tiny language designed to build intuition about how the Lambda Calculus, or more generally, computation-by-substitution works. Rather than the usual interpreter that grinds lambda terms down to values, elsa aims to be a light-weight proof checker that determines whether, under a given sequence of definitions, a particular term reduces to to another.

Online Demo

You can try elsa online at this link

Install

You can locally build and run elsa by

  1. Installing stack
  2. Cloning this repo
  3. Building elsa with stack.

That is, to say

$ curl -sSL https://get.haskellstack.org/ | sh
$ git clone https://github.com/ucsd-progsys/elsa.git
$ cd elsa
$ stack install

Editor Plugins

Overview

elsa programs look like:

-- id_0.lc
let id   = \x -> x
let zero = \f x -> x

eval id_zero :
  id zero
  =d> (\x -> x) (\f x -> x)   -- expand definitions
  =a> (\z -> z) (\f x -> x)   -- alpha rename
  =b> (\f x -> x)             -- beta reduce
  =d> zero                    -- expand definitions

eval id_zero_tr :
  id zero  
  =*> zero                    -- transitive reductions

When you run elsa on the above, you should get the following output:

$ elsa ex1.lc

OK id_zero, id_zero_tr.

Partial Evaluation

If instead you write a partial sequence of reductions, i.e. where the last term can still be further reduced:

-- succ_1_bad.lc
let one  = \f x -> f x
let two  = \f x -> f (f x)
let incr = \n f x -> f (n f x)

eval succ_one :
  incr one
  =d> (\n f x -> f (n f x)) (\f x -> f x)
  =b> \f x -> f ((\f x -> f x) f x)
  =b> \f x -> f ((\x -> f x) x)

Then elsa will complain that

$ elsa ex2.lc

ex2.lc:11:7-30: succ_one can be further reduced

  11  |   =b> \f x -> f ((\x -> f x) x)
              ^^^^^^^^^^^^^^^^^^^^^^^^^

You can fix the error by completing the reduction

-- succ_1.lc
let one  = \f x -> f x
let two  = \f x -> f (f x)
let incr = \n f x -> f (n f x)

eval succ_one :
  incr one
  =d> (\n f x -> f (n f x)) (\f x -> f x)
  =b> \f x -> f ((\f x -> f x) f x)
  =b> \f x -> f ((\x -> f x) x)
  =b> \f x -> f (f x)                 -- beta-reduce the above
  =d> two                             -- optional

Similarly, elsa rejects the following program,

-- id_0_bad.lc
let id   = \x -> x
let zero = \f x -> x

eval id_zero :
  id zero
  =b> (\f x -> x)
  =d> zero

with the error

$ elsa ex4.lc

ex4.lc:7:5-20: id_zero has an invalid beta-reduction

   7  |   =b> (\f x -> x)
          ^^^^^^^^^^^^^^^

You can fix the error by inserting the appropriate intermediate term as shown in id_0.lc above.

Syntax of elsa Programs

An elsa program has the form

-- definitions
[let <id> = <term>]+

-- reductions
[<reduction>]*

where the basic elements are lambda-calulus terms

<term> ::=  <id>
          \ <id>+ -> <term>
            (<term> <term>)

and id are lower-case identifiers

<id>   ::= x, y, z, ...

A <reduction> is a sequence of terms chained together with a <step>

<reduction> ::= eval <id> : <term> (<step> <term>)*

<step>      ::= =a>   -- alpha equivalence
                =b>   -- beta  equivalence
                =d>   -- def   equivalence
                =*>   -- trans equivalence
                =~>   -- normalizes to

Semantics of elsa programs

A reduction of the form t_1 s_1 t_2 s_2 ... t_n is valid if

  • Each t_i s_i t_i+1 is valid, and
  • t_n is in normal form (i.e. cannot be further beta-reduced.)

Furthermore, a step of the form

  • t =a> t' is valid if t and t' are equivalent up to alpha-renaming,
  • t =b> t' is valid if t beta-reduces to t' in a single step,
  • t =d> t' is valid if t and t' are identical after let-expansion.
  • t =*> t' is valid if t and t' are in the reflexive, transitive closure of the union of the above three relations.
  • t =~> t' is valid if t normalizes to t'.

(Due to Michael Borkowski)

The difference between =*> and =~> is as follows.

  • t =*> t' is any sequence of zero or more steps from t to t'. So if you are working forwards from the start, backwards from the end, or a combination of both, you could use =*> as a quick check to see if you're on the right track.

  • t =~> t' says that t reduces to t' in zero or more steps and that t' is in normal form (i.e. t' cannot be reduced further). This means you can only place it as the final step.

So elsa would accept these three

eval ex1:
  (\x y -> x y) (\x -> x) b 
  =*> b

eval ex2:
  (\x y -> x y) (\x -> x) b 
  =~> b

eval ex3:
  (\x y -> x y) (\x -> x) (\z -> z) 
  =*> (\x -> x) (\z -> z) 
  =b> (\z -> z)

but elsa would not accept

eval ex3:
  (\x y -> x y) (\x -> x) (\z -> z) 
  =~> (\x -> x) (\z -> z) 
  =b> (\z -> z)

because the right hand side of =~> can still be reduced further.

More Repositories

1

liquidhaskell

Liquid Types For Haskell
Haskell
1,183
star
2

liquid-fixpoint

Horn Clause Constraint Solving for Liquid Types
Haskell
134
star
3

liquidhaskell-tutorial

Tutorial for LiquidHaskell
JavaScript
73
star
4

mist

A tiny language for teaching and experimenting with Refinement Types
Haskell
47
star
5

230-wi19-web

Public course materials for CSE 230 (Winter 2019)
Haskell
27
star
6

lh-plugin-demo

A small package that demonstrates how to use LiquidHaskell as a GHC plugin
Haskell
23
star
7

131-web

Public course materials for CSE 131 (Compilers)
JavaScript
18
star
8

liquid-types-spacemacs

Spacemacs Layer for LiquidHaskell
Emacs Lisp
13
star
9

lh-workshop

Materials for 2-hr LiquidHaskell Workshop
JavaScript
11
star
10

liquid-sf

Port "Software Foundations" to LiquidHaskell
Haskell
11
star
11

nate

Learning to Blame Type Errors from Novice Mistakes
OCaml
10
star
12

dsolve

DSOLVE
OCaml
8
star
13

intro-refinement-types

Introductory Tutorial on Refinement Types
JavaScript
8
star
14

liquidhaskell-blog

LiquidHaskell blog
JavaScript
8
star
15

liquid-types.vim

Vim support for Liquid Types
Vim Script
6
star
16

nanomaly

JavaScript
5
star
17

csolve

full csolve repo
C
5
star
18

liquid-fixpoint-ocaml

Haskell Interface for Back-End Implication / Horn Clause Constraint Solving for Liquid Types
Haskell
5
star
19

yunounderstand-data

A collection of novice interactions with the OCaml top-level.
OCaml
4
star
20

131-public

Course materials for undergraduate compilers class
4
star
21

liquid-server

Web Server for Liquid-Types demos.
JavaScript
3
star
22

liquidhaskell-tutorial-solutions

Solutions for LH tutorial
Haskell
2
star
23

csv-table

Scripts for manipulating tables stored as CSV files
Haskell
2
star
24

lh-plugin-demo-client

Client package that shows how to import LH specifications from an external package
Haskell
2
star
25

AbstractRefinementTypes

2
star
26

liquid-logger

Scripts for analyzing LiquidHaskell benchmark logs
Haskell
2
star
27

tagged-timers

Simple wrappers for timing IO actions (single-threaded)
Haskell
1
star
28

plot-benchmarks

Program to generate performance graphs from test logs
Haskell
1
star
29

csolve-bak

Liquid Types for C
C
1
star
30

liquidhaskell-interactive

Persistent LiquidHaskell Server To Enable Fast Interactive/Incremental Checking
Haskell
1
star
31

proofs-of-data

Proving properties of various data structures with LiquidHaskell (Port of Appel's VFA)
Haskell
1
star