Below written from pov that functional programming (FP) is the only way to go.
This is of course not literally true. But people of other viewpoints can express their's better than I can. So I'll stay with mine; here goes!
Constructing the Ideal CS-101 language
The PL-no-1 becomes willy-nilly the mentalese or Language of Thought for the student for their life. Or at least for a long time after. So it behoves us to make good choices here!
Following are the desiderata I consider key and the closest corresponding ideal language. Here's a wider set. I invite you to think through your own personal set. Main point being:
Decide your attributes before your language.
The medium for CS-101 should:
- Have low bar on use : Python
- Have clean type inference : ML
- Be conceptually simple : Scheme
- Have rich expressions : APL
- Have a mathematical (aka equational) feel : Haskell
Scott Rowe (and like-minded) will exclaim: Where in all this is...
The machine that makes this world possible?!
Yes machine understanding matters. But postponing that causes less damage than reversing the order to machine-first and have students get into the bad habit of getting hung up on implementation/efficiency questions and neglect semantics. This is of course the point around which the maximum amount of disagreements and disputes occur. I don't claim to be without bias. I only claim to be on the better side😉.
My slogan here:
Semantics before efficiency;
Ontology before semantics
This answer will make sense if that is agreeable.
If its not you probably want to stop reading here!
The first part of the slogan is sufficiently over quoted that I can leave it alone. The second is less known... And more important
When we teach there are two things that interact:
- the concepts we wish to teach
- the key-elements of the PL used
Both these are the ontologies though from different domains.
When they gel the flow is smooth: rewarding to teacher, illuminating to student.
When not it becomes like Bernard Shaw's pig metaphor:
Never wrestle with a pig. You get dirty, and besides, the pig likes it.
The last may be unverifiable but the rest stands
When the course objectives (teacher ontologies) and the PL's ontologies mismatch everyone suffers
An example: Lists ("singly linked lists") in C start with:
T elem; /* Whatever T may be */
struct node *next;
Did you notice that there are TWO types there? No?? Let me spell it out
typedef node *nodeptr;
nodeptr is the concrete C model for the abstract list type?
Now you may consider this a hairsplitting question but it becomes key from the ontology pov. Because from the ontology-pov the abstract list type falls between the two concrete C types
In effect then all of C is coding up around the fact that:
Not only C has no lists; it does not even have user defined lists
[If you disagree with that look at Greenspun's tenth rule]
IOW I discard the machine-first without much compunction.
I also discard the OOP-first philosophy. Justifications for this are for elsewhere...
But there are other desiderata that are more real. I happen to choose to de-prioritize them. Others may — justifiably — choose otherwise. For example
- FP is proverbially a good fit for parallel programming. If this matters Erlang will come high on your list. And if high becomes highest — great!
- Real world considerations invariably push against academic ones:
- Must be under JVM : Scala, Clojure
- Windows/.NET are my world : F#
- You really want to push the FP envelope at its research-edges? Idris, Agda
- The main action is at meta level (you are a devotee/disciple of Paul Graham)? Common Lisp
There are dozens (maybe hundreds) of other attributes we could study.
All these have their legitimate provenance. They are just not important enough for me… at the moment. [I wouldn't put it past Idris/Agda taking over the mantle of Haskell in 2035]
Problem with OOP: You wanted a banana. You got a gorilla holding the banana and the entire jungle.
My general suggestion would be towards this: You wanted FP. You chose Haskell.
Did you want the 700lb gorilla?
This is usually taken as the FP-er Armstrong bashing OOP
I am turning it round to and applying it to Haskell! There's just way way way too too much there. For the sophisticated programmer it could be joyous like slurping around Willy Wonka's chocolate factory. To the beginner its more like getting drowned.
The trouble is that scheme really doesnt cut it as an FPL by 2022 standards.
Much of Scott Rowe's continual tirades against scheme come from this: If they (SICP) were going to introduce assignment on pg 300 and invalidate those earlier 300 pages why did they waste my time?
The problem — this problem — vanishes in Haskell: You cant do assignment/mutation… pg 3 Or 300 Or 3000. Not possible. Its just not there.
The question is a non-trivial one; viz: How far to push in important desiderata? Informally into the culture? Or all the way formally into the language definition?
At the broader level the view (to me at least) is murky.
At the beginner level its quite clear Haskell gets (this aspect!) righter than scheme
Haskell → Haskellish
Haskell is great but Haskell has lost its way into labyrinthine complexity of its legendary type system. See
- Erik Meijer Popular MOOC on FP
- Mark Lentczner resignation from release manager for The Haskell Platform
- Simple Haskell A bunch of folks feeling similarly
- Google for ftp/amp for more nittygritty details about the controversy eg
As a teacher, I wish to stay Haskell-ISH but not Haskell proper as in current ghc at least for CS-101. [Projects is another matter]
Below I suggest alternatives for those who are convinced that Haskell-style FP is the way to go but not ghc itself (for now)
Nearest to Haskell
The original small super elegant expensive proprietory predecessor of Haskell. Recently open sourced. Strongly recommended for teaching basic programming via FP.
A natural first choice for people who regard Bird&Wadler (Ed-1 mind you!) as the best CS book ever See interview
Earliest and smallest language that can claim to be Haskell.
See Haskell-gofer error message comparison
The big thing going for it are the series of preludes that make it possibly to sequentially add complexity as Racket does with its teachpacks.
My changes to gofer which I most use.
No this is not a "shameless plug". Its not documented for public use. Not really usable other than by my students/colleagues.
Can reasonably be called "gofer 2"; falls between gofer and full (modern) haskell; a very sane choice for people going functional; as Erik Meijer demonstrated a few years ago
Similar goals to pugofer in terms of beginner simplicity. See
When we get that the whole business of using FP as a general programming ideology is using math equations as a term reqriting system, an explcit rewriting-oriented language becomes an attractive choice. Pure is one such.
[No first hand experience]
- Erlang : When concurrency is central
- ML family (SML Poly-ML, CAML, OCAML) : the original FPLs. In many ways neater than all the rest.
- Stay within the Java world : Clojure, Scala
- Stay within the .NET : F#
Especially given your:
I learnt FP using SML decades ago
ML-family may be the sanest choice. Conversely using current publicity ratings to determine a CS-101 medium is really egregious. For those who don't see this there's no use to this conversation. For those who do, there's no need. Still it may help to hear a Dijkstra hyperbole:
Programming should be taught with a language not implemented on campus
Now you can ignore that, or take it literally. I hear it as Dijkstra giving us teachers the freedom to cock a snook at TIOBE indices!
In short my recommendation
For you Ben take ML family if that makes you most comfortable. At least to start with.
[Others can sift the set nearest Haskell to their taste]
I actually like ML family a great deal. Much more teacher-friendly and fad-unfriendly than the modern crop.
Myself I dont use it because I am addicted to Haskell syntax.
[My ideal FPL would be an ML-semantics carrying a Haskellish syntax. No such exists that I know]
Call me silly but I really want my quick sort to be thusly
qsort  = 
qsort (x::xs) = qsort [y | y ∈ xs, x<y] ++ [x] ++ qsort [y | y ∈ xs, x≥y]
Yeah my emacs is setup so that when I type
<- I get