writings/10/9/2022

(CalcLang using Coalton (Types in Common Lisp))

Coalton (Common Lisp With Types)

I have been using Common Lisp to work on this site now for about a week. I have had tons of fun so far working on it. I work on it everyday in some format. Using Common Lisp has been a good experience even with having to parse through libraries and reading through lots of code.

The last post I was working on was using Elm to build an interpreter for a small Calc Lang. That was cool I wanted to continue working on that but also I wanted to work in Common Lisp. So I thought I would try and bring the paper into Common Lisp. Quickly, I realized that I really wanted stronger types. Not because I couldn't do it without them but because having them in this case would greatly enhance my understanding.

Coalton allows us to bring some typefu into Common Lisp

Downloading Coalton

Note that Coalton at the time of this writing is still in active development so all of this may not work in the future. So do check out the documentation at the repo.

Also check out the intro tutorial

    git clone git@github.com:coalton-lang/coalton.git /quicklisp-directory/local-projects/ 

Installing Coalton

Coalton is not yet in Quicklisp so we will need to install it by adding it to our local-projects directory so that we can install it with Quicklisp.

    (ql:quickload :coalton)  

Now that we have it loaded we can start experimenting first in the repl.

Lets switch into the coalton-user package

    (in-package #:coalton-user) 

Motivation

Before we explore Coalton, lets revisit my motivation. I wanted to write a function that essentially evaluates a calculator language with one operation Addition and numbers. This is what is was looking like in plain lisp initially.

    (defun addp (expr)  
        (and (consp expr)  
         (eq (car expr) 'ADD)))  
 
    (defun calc (expr)  
        (cond  
            ((numberp expr) expr)  
            ((addp expr)  
                (+ (calc (cadr expr))  
                    (calc (caddr expr)))))) 

I was getting frustrated here because I had to track the representation of the type at the same time and maybe that was due to poor naming but lets see what we get with Coalton.

Ok so some of my frustration was that I had to think about how I was going to represent my type instead of just being able to create a sum type to experiment with.

Well in Coalton, I can get my types immediately. Place this in a file and compile it in the repl.

    (coalton-toplevel  
        (define-type Expr  
         (Val Integer)  
         (Add Expr Expr)))  

Then in the repl you can now experiment with our types

COALTON-USER> (coalton (Add (Val 3) (Val 3))) 

#.(ADD #.(VAL 3) #.(VAL 3))

Well now that is over can we write calc

(define (calc expr)  
    (match expr  
        ((Val r ) r)  
        ((Add x y ) (+ (calc x) (calc y))))) 

Ok that was easy can we make a Stack

(declare calcs (Expr -> (List Integer) -> (List Integer)))  
(define (calcs expr stack)  
    (match expr  
    ((Val r ) (cons r stack))  
    ((Add x y ) (add-stack (calcs y (calcs x stack) )))))  

I think this is cool place to stop and marvel at the intersection of Lisp and types.

I will revisit Coalton for sure.