
Typed Lisp, a Primer (2019) - jedimind
https://alhassy.github.io/TypedLisp.html
======
vindarel
It's a great article. Related, for Common Lisp:
[https://lispcookbook.github.io/cl-
cookbook/type.html](https://lispcookbook.github.io/cl-cookbook/type.html)

and also:

\- [https://medium.com/@MartinCracauer/static-type-checking-
in-t...](https://medium.com/@MartinCracauer/static-type-checking-in-the-
programmable-programming-language-lisp-79bb79eb068a) (by an author of the
CLASP implementation, C++ & LLVM for CL)

\-
[https://github.com/stylewarning/coalton](https://github.com/stylewarning/coalton)
\- a library (pre-alpha): adding Hindley-Milner type checking to Common Lisp
which allows for gradual adoption, in the same way Typed Racket or Hack allows
for. It is as an embedded DSL in Lisp that resembles Standard ML or OCaml, but
lets you seamlessly interoperate with non-statically-typed Lisp code (and vice
versa).

------
dustingetz
Clojure's take on types is not so much that types are bad at micro scale, it's
that focusing on proving referential transparency above all else leads to
cultural problems at the macro scale. For example, the Datomic Peer API is the
most elegant and ergonomic database API I've ever seen. Queries compose as
functions under the illusion that the database is a local data structure and
this results in a beautiful information model. But if you tried to put IO
types on Datomic you find that it spews IO everywhere. And yet it works
incredibly well with good enough performance for a wide band of applications!
I think you don't find stuff like that in Pure FP ecosystems because those
communities coordinate under principles of RT and algebra, and are thus unable
to consider a solution space rooted in a different set of principles.

~~~
lmm
> But if you tried to put IO types on Datomic you find that it spews IO
> everywhere.

So you put it in a monad and get on with your life? It's like one or two extra
characters on your operators just to mark out where you're doing effect
composition, and the benefit is that you can immediately see where all the
effects are happening. Code is read more than it's written, so it's a really
good tradeoff.

> And yet it works incredibly well with good enough performance for a wide
> band of applications!

How big is it, and how many people work on it? IME not tracking effects works
great as long as everyone working on the codebase can keep the whole thing in
their head. But you hit a wall (for me it's about 20kloc - I'm sure smarter
people can push it a bit further, but everyone will have a limit eventually)
once you can no longer reason about how one part affects every other part, and
at that point a little helping hand from the compiler helps a lot.

~~~
dustingetz
The closest thing I can think of from the pure FP community that makes queries
compose in a monad is Scala Slick, which adds an extraordinary amount of
complexity to compose queries in exactly the wrong way. The whole FP
community's thesis seems to be "take adderall and follow the math" and that
thesis leads to Slick, not Datomic. (Both are early 2010s era so i think this
is a fair comparison)

~~~
lmm
Slick is for querying traditional SQL RDBMSes, so it has to deal with a
massive impedance mismatch compared to a greenfield project. I'd look at
something like Facebook's Haxl (for querying GraphQL) for a fairer comparison
IMO.

------
spellcard199
After trying Typed Clojure, liking it, but giving it up because of Clojure's
GPL-incompatible license, I got interested in Kawa Scheme because it has some
rudimentary form of type checking. For example, this produces warnings:

    
    
      (define (f1 x::String y::String) (x:concat y))
      (define (f2) (f1 3 3))
    
      ;; /dev/tty:3:19: warning - type integer is incompatible with required type java.lang.String
      ;; /dev/tty:3:21: warning - type integer is incompatible with required type java.lang.String
      ;; /dev/tty:3:15: warning - cannot convert literal (of type gnu.math.IntNum) to Type java.lang.String
      ;; /dev/tty:3:15: warning - cannot convert literal (of type gnu.math.IntNum) to Type java.lang.String
    

Unfortunately it does not support fully static type checking nor generics,
otherwise it would be my favorite scripting language hands down.

As for type checking Elisp, Elsa[1] seems an interesting project and I hope it
becomes a stable option. On the other hand I wonder if in future type checking
could also come from gccemacs[2], since one of the "long-term improvements"
may be "better compile time warning and errors relying on the propagation
engine".

[1] [https://github.com/emacs-elsa/Elsa](https://github.com/emacs-elsa/Elsa)
[2] [https://akrl.sdf.org/gccemacs.html](https://akrl.sdf.org/gccemacs.html)

Edit: grammar.

~~~
smabie
Typed Racket tends to work pretty well, and you can gradually add types to
dynamic code. Probably the most mature type system of any Lisp.

And if you feel like types are too constraining for a part of your code, you
can just leave them out. You get the best of both worlds!

~~~
caltelt
I was really excited when I started using racket that I could switch to static
typing when I wanted it. However after trying out contract's, I must say I'm
quite a fan of them as an alternative. Sure, you lose out on static, compile
time checking, but honestly, I haven't missed it. And it's _even more_
seamlessly integrated into un-contracted code. You can express more
interesting things and complex relationships between parameters using the ->i
contract than any type system I know of will allow. There's some limitations,
but between it and unit testing, I've been having a blast.

~~~
smabie
Contracts incur absolutely massive performance penalties. Sparingly used, they
can provide value though.

There's no reason why you can't have types and contracts though. I personally
can't live without compile time guarantees.

~~~
zelphirkalt
I've tried racket/typed before and my knowledge or experience with it might be
outdated, but sometimes I just could not get it to agree with my code. I fix
one typing warning or thing it cannot infer and another would pop up. I fix
the other, then a third pops up. I try to fix the third one, but realize I
cannot and need to go back to the original state. When such things do not
happen, it is very cool though. The code behing typed racket for me seems so
mind bogglingly complex, I did not dare to investigate further. It is a
language composed of macros, which use rackets macrology stuff, which is
already more complex than other Schemes'. That language can be used to design
any type system as far as I read about it.

With my typing trouble I should have come to the user list and asked, but I
dId not, frustrated and thinking I was too stupid to get it ^^'

I did once at least see a question on the mailing list, where the answer was,
that typed racket could not do it, as in infer types, so it might not be
perfect yet, or perhaps it did improve since then.

I wish more Schemes could just copy the typed part of typed racket, using that
macro language, as in theory they should be able to represent it, but I guess
the devil is in the detail and slightly different workings of macro
facilities.

~~~
smabie
Racket has a much more advanced macro system than scheme's traditional syntax-
case.

~~~
zelphirkalt
Yes, it certainly has, but I think it's still based on that traditional
syntax-case stuff. So in theory other Schemes could perhaps copy it, if anyone
can get all the macrology behind it. Also in theory it should be possible to
express all the advanced Racket stuff in syntax-case.

Do you think it is not possible to express these things in syntax-case? And if
so, why?

------
User23
CMUCL, and I assume SBCL by extension, has a rich type inference system[1]
that I wish were more widely known.

[1] [https://pmsf.eu/pub/cmucl/doc/cmu-user-
old/compiler.html#toc...](https://pmsf.eu/pub/cmucl/doc/cmu-user-
old/compiler.html#toc125)

------
dependenttypes
That reminds me, PG wrote that "static typing seems to preclude true macros"
in
[http://www.paulgraham.com/hundred.html](http://www.paulgraham.com/hundred.html)
despite it being obviously incorrect.

------
swatson741
This is a good article but, the author doesn't show the limitations of type
systems. If our world is small enough types can be very useful. There are many
situations where we want to work in a small world.

>type's have always been there

I've seen this argument before and, I disagree with this statement as
presented. The implication is that there is a type system underlying a
language's semantics. But, really that's not true. It's more correct to say
that objects have always been there.

