Hacker News new | ask | show | jobs
by agomez314 942 days ago
Great resource! Forgive my ignorance but why do so many modern functional programming courses use Standard ML instead of a Lisp dialect? Is it because of its built-in type-checking, or is it just how it's always been taught?
5 comments

The value of purely functional programming languages, as opposed to functional programming languages like lisps, is that you get referential transparency, which means that when you define `a = b`, you know that you can always replace any instance of `a` with `b` and get the same answer. This is a very natural property in mathematics (algebraic rewritings are basically just this property writ large) and so it helps to draw nice parallels between the familiar notation of functions from mathematics and the "new" and "confusing" notion of functions in functional programming and other declarative languages.

As other posters have said, strong typing is also a nice property for lots of reasons, most notably it gives a platform to talk about ad-hoc and parametric polymorphism.

(I lecture on Functional Programming at the University of Warwick, where we use Haskell.)

I think SML isn't purely functional (although it naturally encourages a purely functional style).
The first problem with this argument is that referential transparency is a property of syntactic positions, not of languages.

The second is that languages like Lisp, SML, C, Pascal and BASIC all have referentially transparent and referentially opaque positions in exactly the same way that languages like Haskell do.

This means that all these languages enjoy referential transparency in the same way, because when you unpack the notion of equivalence, referential transparency itself is within a whisker of being a tautology: if a is equivalent to b, then you can substitute a for b or b for a. The relevant sense for "is equivalent to" can really only be contextual equivalence, which is all about meaning-preserving substitutability.

That said, not having to reason about effects within one's program equivalence sure makes things simpler in a pedagogical setting. But that's not to do with referential transparency per se.

For those of us who are unfamiliar with Lisps, can you expand on how they break referential transparency (and how Standard ML contrasts in that regard)?
They don’t.

Or at least not inherently, if by “lisp” one is primarily referring to s-expressions.

He is probably talking about namespaces. In common lisp, for example,

   (a a)
calls a function 'a' on a variable 'a'. Lisp knows this because the first thing that comes after the left paren is a function
more importantly there are functions (using scheme as an example) like set! and set-cdr! that mutate existing values and totally break referential transparency.

this isn't just user facing - for example let* kind of depends on creating bindings up front so they work across clauses, and then mutating them afterwards

Why does `let*` need to have mutation? It can be nested `let`s.
let* permits expressions on the right refer to arbitrary other symbols bound by the let*. in particular it allows for construction of recursive lambdas that may not be linearlizable.
Lisp allows you to mutate, you can certainly write non-mutating code in lisp. Why do you think you need to use mutation with let*? let* is just a sequential let

https://www.lispworks.com/documentation/lw70/CLHS/Body/s_let...

"Lisp" is pretty broad. Whilst it was inspired by Lambda Calculus (the core of most FP languages), a lot of Lisp code is quite imperative (loops, mutable variables, control flow separate from data flow (e.g. exceptions/errors), etc.).

Scheme (and its dialects/descendants) tend to stick to a more functional style (although they also like to do stack-gymnastics with continuations, etc.). Many courses are based around Lisp.

One of the main features of the ML family is static typing, with algebraic datatypes, pattern-matching, etc. (i.e. the stuff that new languages like to call "modern", because they first saw it in Swift or something). That gives a useful mathematical perspective on code ("denotational semantics", i.e. giving meaning to what's written; as opposed to the common "operational semantics" of what it made my laptop do), and having type checking and inference makes it easier to do generic and higher-order programming (dynamic languages make that trivial in-the-small, but can make large systems painful to implement/debug/maintain/understand). This course seems to take such abstraction seriously, since it covers modules and functors too (which are another big feature of the ML family).

NOTE: In ML, the words "functor" and "applicative functor" tend to mean something very different (generic, interface-based programming) to their use in similar languages like Haskell (mapping functions over data, and sequencing actions together)

It is statically typed, there's a lot of depth to that side of things (Curry-Howard isomorphism)
My opinion: marketing. In my experience, if I tell someone „look here is Lisp“ they turn off and roll the eyes with a „ohh that DEAD origramming language“. If I instead say „look this new state of the art language called ML“ I get full attention and respect.
No, it's definitely not because of marketing. SML is more of a dead language than most lisps. SML is used because it has a strong type checker, which is much more conducive to learning, and just having resilient programs in general.
Why would they use a Lisp dialect instead of Standard ML? It looks ugly, it looks different from math, and different concepts have the same syntax. Standard ML looks nice, it looks like math, and different concepts have different syntax.
No, SML is actually quite verbose ang generally ugly, compared to say OCaml or F#, or even Scheme or Closure. This is why it is dead.