Coalton Playground: Type-Safe Lisp in the Browser

36 reikonomusha 7 8/13/2025, 3:00:33 PM abacusnoir.com ↗

Comments (7)

anentropic · 27m ago
Layout is broken on non-maximised window sizes (text overflows off the right edge of the page)

EDIT: I'm referring to layout of the blog post in the thread title, the https://coalton.app/ is ok

anentropic · 22m ago
FYI coalton.app "Type Classes" example has "Error: unmatched close parenthesis" when you run it

"JSON Parser" example also has errors

CraigJPerry · 39m ago
Is Coalton not more about performance, removing the dynamicism - lisp (at least SBCL) is already type-safe. Or it behaves that way in my limited experience - e.g. i get feedback when i screw up.

I'm completely clueless about Coalton, (and almost completely an idiot when it comes to CL more generally - been playing for a couple of years at this point but even so, every day is still a school day...)

skulk · 8m ago
FWIW, SBCL is pretty good at optimizing away dynamic type checks if you help it out.

Here are some examples under:

    (declaim (optimize (speed 2)))
First example is a generic multiplication. x and y could be _any_ type at all.

    (defun fn (x y) (* x y))
If we disassemble this function, we get the following:

    ; disassembly for FN
    ; Size: 34 bytes. Origin: #x1001868692                        ; FN
    ; 92:       488975F8         MOV [RBP-8], RSI
    ; 96:       4C8945F0         MOV [RBP-16], R8
    ; 9A:       498BD0           MOV RDX, R8
    ; 9D:       488BFE           MOV RDI, RSI
    ; A0:       FF142540061050   CALL [#x50100640]                ; SB-VM::GENERIC-*
    ; A7:       4C8B45F0         MOV R8, [RBP-16]
    ; AB:       488B75F8         MOV RSI, [RBP-8]
    ; AF:       C9               LEAVE
    ; B0:       F8               CLC
    ; B1:       C3               RET
    ; B2:       CC0F             INT3 15                          ; Invalid argument count trap
Note that it calls `GENERIC-*` which probably checks a lot of things and has a decent overhead.

Now, if we tell it that x and y are bytes, it's going to give us much simpler code.

    (declaim (ftype (function ((unsigned-byte 8) (unsigned-byte 8)) (unsigned-byte 16)) fn-t))
    (defun fn-t (x y) (* x y))
The resulting code uses the imul instruction.

    ; disassembly for FN-T
    ; Size: 15 bytes. Origin: #x1001868726                        ; FN-T
    ; 26:       498BD0           MOV RDX, R8
    ; 29:       48D1FA           SAR RDX, 1
    ; 2C:       480FAFD7         IMUL RDX, RDI
    ; 30:       C9               LEAVE
    ; 31:       F8               CLC
    ; 32:       C3               RET
    ; 33:       CC0F             INT3 15                          ; Invalid argument count trap*
tmtvl · 27m ago
In CL you can't declare, for example, a proper-list-of type, which is to say a type which accepts a second type and represents a proper list containing only members of that second type.

  (deftype Proper-List-Of (subtype)
    `(or Null
         (Cons ,subtype
               (Proper-List-Of ,subtype))))
Doesn't work (for example). There kind of are ways to work around it to some extent with satisfies and ad-hoc predicate generation, but Coalton is a true value add in that aspect.
wild_egg · 28m ago
CL is strongly typed but not statically typed. The compiler generally doesn't complain ahead of time that your function is going to do math on a string because it was called incorrectly. Typically a runtime condition will be signalled when it hits that point and you can sort it out from there.

Coalton moves that to the compilation step so you get an error back the instant you send the form to the REPL.

asplake · 31m ago
I’ve looked at it rather than used it, but what it brings is ML-style polymorphism. Type safety is a given in that case, which may or may not be the case with CL (I’ll let others argue that one).