recomiendo pure-lang para estos fines pedagógicos. También es bastante poderoso. Si quiere algo más popular/con más apoyo de la comunidad, entonces le recomendaría Scheme u OCaml, dependiendo de si prefiere tratar con sintaxis desconocida (vaya con Scheme) o trate primero con mecanografía desconocida (vaya con OCaml). SML y F # son solo ligeramente diferentes de OCaml. Otros han mencionado o mencionarán a Clojure, Scala y Haskell.
Clojure es una variante de Scheme, con sus propias idiosincrasias (por ejemplo, sin optimización de la cola de llamada), por lo que su uso sería una forma de comenzar con Scheme. Sin embargo, esperaría que le resultara más fácil con una implementación del Esquema menos idiosincrásica. Racket es lo que se usa a menudo para enseñar. Scala parece ser fundamentalmente similar a OCaml, pero esto se basa solo en la familiaridad informal.
A diferencia de Haskell, los otros idiomas mencionados tienen dos ventajas: (1) el orden de evaluación está ansioso por defecto, aunque puede obtener una evaluación diferida solicitándolo específicamente. En Haskell está al revés. (2) La mutación está disponible, aunque la mayoría de las bibliotecas y el código que verá no la usarán. De hecho, creo que es pedagógicamente mejor aprender programación funcional y, al mismo tiempo, observar cómo interactúa con los efectos colaterales, y trabajar en la composición de estilo monádico un poco más adelante. Entonces creo que esto es una ventaja. Sin embargo, algunos te dirán que, sin embargo, es mejor tirarse al manejo más en cuarentena de Haskell de mutaton.
Robert Harper en CMU has some nice blog posts on teaching functional programming. Según entiendo, también prefiere idiomas como OCaml para la enseñanza.
Entre las tres clases de idiomas que recomendé (Pure, Scheme y amigos, OCaml y amigos), las dos primeras tienen tipado dinámico. El primero y el tercero tienen celdas de referencia explícitas (como si en Python, se restringiera a nunca reasignar una variable pero aún podría cambiar lo que está almacenado en un índice de lista). El esquema tiene celdas de referencia implícitas: las variables mismas parecen mutables, como en C y Python, y el manejo de la celda de referencia se realiza bajo las cubiertas. En idiomas como ese, a menudo también tiene disponible algún tipo de celda de referencia explícita (como en el ejemplo que acabo de dar en Python, o usando pares/listas mutables en Racket ... en otros esquemas, incluido el estándar Scheme, esos son los pares/listas predeterminadas).
Una virtud que tiene Haskell es que algunos libros de texto están apareciendo para ella. (Me refiero a esto sinceramente, no irritablemente.) Qué libros/recursos usar es otro tema controvertido con muchas guerras/preguntas cerradas. SICP como otros han recomendado tiene muchos fans y también algunos críticos. Me parece que hay muchas buenas opciones. No me aventuraré más en esos debates.
Haskell a menudo se recomienda aprender el paradigma funcional, ya que es puro. No es fácil, pero quizás te confundas al mezclar el paradigma funcional y de procedimiento en otros idiomas (Scala y otros). – MatijaSh