Domanda

Insegnerò un corso di divisione inferiore in strutture discrete. Ho selezionato il libro di testo Strutture discrete, logica e calcolabilità in parte perché contiene esempi e concetti che favoriscono l'implementazione con un linguaggio di programmazione funzionale. (Penso anche che sia un buon libro di testo.)

Voglio un linguaggio FP di facile comprensione per illustrare i concetti di DS e che gli studenti possano usare. La maggior parte degli studenti avrà avuto solo uno o due semestri di programmazione in Java, nella migliore delle ipotesi. Dopo aver esaminato Scheme, Erlang, Haskell, Ocaml e SML, ho optato per Haskell o Standard ML. Mi sto sporgendo verso Haskell per i motivi indicati di seguito, ma mi piacerebbe l'opinione di coloro che sono programmatori attivi nell'uno o nell'altro.

  • Sia Haskell che SML hanno un pattern matching che rende la descrizione di un algoritmo ricorsivo un gioco da ragazzi.
  • Haskell ha una buona comprensione delle liste che si abbina bene al modo in cui tali liste sono espresse matematicamente.
  • Haskell ha una valutazione pigra. Ottimo per costruire liste infinite usando la tecnica di comprensione delle liste.
  • SML ha un interprete veramente interattivo in cui le funzioni possono essere sia definite che utilizzate. In Haskell, le funzioni devono essere definite in un file separato e compilate prima di essere utilizzate nella shell interattiva.
  • SML fornisce una conferma esplicita dell'argomento della funzione e restituisce i tipi in una sintassi che è facile da capire. Ad esempio: val foo = fn: int * int - > Int. La sintassi implicita del curry di Haskell è un po 'più ottusa, ma non totalmente aliena. Ad esempio: foo :: Int - > Int - > Int.
  • Haskell utilizza numeri interi di precisione arbitraria per impostazione predefinita. È una libreria esterna in SML / NJ. E SML / NJ tronca l'output a 70 caratteri per impostazione predefinita.
  • La sintassi lambda di Haskell è sottile - usa una singola barra rovesciata. SML è più esplicito. Non sono sicuro se avremo mai bisogno di lambda in questa classe, però.

In sostanza, SML e Haskell sono approssimativamente equivalenti. Mi rivolgo a Haskell perché adoro la comprensione delle liste e le liste infinite in Haskell. Ma sono preoccupato che il vasto numero di simboli nella sintassi compatta di Haskell potrebbe causare problemi agli studenti. Da quello che ho raccolto leggendo altri post su SO, Haskell non è raccomandato per i principianti che iniziano con FP. Ma non costruiremo applicazioni a tutti gli effetti, solo provando semplici algoritmi.

Cosa ne pensi?


Modifica: dopo aver letto alcune delle tue ottime risposte, dovrei chiarire alcuni dei miei punti elenco.

In SML non esiste alcuna distinzione sintattica tra la definizione di una funzione nell'interprete e la definizione in un file esterno. Diciamo che vuoi scrivere la funzione fattoriale. In Haskell puoi inserire questa definizione in un file e caricarlo in GHCi:

fac 0 = 1
fac n = n * fac (n-1)

Per me è chiaro, conciso e corrisponde alla definizione matematica del libro. Ma se vuoi scrivere direttamente la funzione in GHCi, devi usare una sintassi diversa:

let fac 0 = 1; fac n = n * fac (n-1)

Quando si lavora con interpreti interattivi, dal punto di vista dell'insegnamento è molto, molto utile quando lo studente può usare lo stesso codice sia in un file che nella riga di comando.

Con "esplicita conferma della funzione", " Volevo dire che dopo aver definito la funzione, SML ti dice subito il nome della funzione, i tipi degli argomenti e il tipo restituito. In Haskell devi usare il comando : type e poi ottieni la notazione al curry un po 'confusa.

Un'altra cosa interessante di Haskell: questa è una definizione di funzione valida:

fac 0 = 1
fac (n+1) = (n+1) * fac n

Ancora una volta, questo corrisponde a una definizione che potrebbero trovare nel libro di testo. Non posso farlo in SML!

È stato utile?

Soluzione

Per quanto ami Haskell, ecco i motivi per cui preferirei SML per una classe in strutture matematiche e dati discrete (e la maggior parte delle altre classi per principianti):

  • I costi di tempo e spazio dei programmi Haskell possono essere molto difficili da prevedere, anche per gli esperti. SML & nbsp; offre modi molto più limitati per far esplodere la macchina.

  • La sintassi per la definizione della funzione in un interprete interattivo è identica alla sintassi utilizzata in un file, quindi è possibile tagliare e incollare.

  • Sebbene il sovraccarico dell'operatore in SML sia totalmente falso, è anche semplice. Sarà difficile insegnare un'intera classe in Haskell senza dover entrare in classi di tipo.

  • Lo studente può eseguire il debug utilizzando print . (Anche se, come sottolinea un commentatore, è possibile ottenere quasi lo stesso effetto in Haskell usando Debug.Trace.trace.)

  • Infinite strutture di dati fanno esplodere le menti delle persone. Per i principianti, è meglio avere loro definire un tipo di flusso completo di celle di riferimento e thunk, in modo che sappiano come funziona:

    datatype 'a thunk_contents = UNEVALUATED of unit -> 'a
                               | VALUE of 'a
    type 'a thunk = 'a thunk_contents ref
    val delay : (unit -> 'a) -> 'a thunk
    val force : 'a thunk -> 'a
    

    Ora non è più magico e puoi passare da qui a stream (elenchi infiniti).

  • Il layout non è così semplice come in Python e può creare confusione.

Ci sono due posti in cui Haskell ha un vantaggio:

  • Nel core Haskell puoi scrivere la firma del tipo di una funzione appena prima della sua definizione. Questo è estremamente utile per studenti e altri principianti. Semplicemente non c'è un buon modo per gestire le firme dei tipi in SML.

  • Haskell ha una migliore sintassi concreta. La sintassi di Haskell rappresenta un notevole miglioramento rispetto alla sintassi ML. Ho scritto una una breve nota su quando usare le parentesi in un Programma ML ; questo aiuta un po '.

Infine, c'è una spada che taglia in entrambi i modi:

  • Il codice Haskell è puro per impostazione predefinita, quindi è improbabile che i tuoi studenti si imbattano per caso in costrutti impuri (monade IO, monade statale). Ma per lo stesso motivo, non possono stampare, e se vuoi fare I / O allora al minimo devi spiegare la notazione do e return è confuso.

Su un argomento correlato, ecco alcuni consigli per la preparazione del corso: non trascurare Strutture di dati puramente funzionali di Chris Okasaki. Anche se i tuoi studenti non lo usano, vorrai sicuramente averne una copia.

Altri suggerimenti

Insegniamo a Haskell ai primi anni nella nostra università. I miei sentimenti al riguardo sono un po 'confusi. Da un lato insegnare a Haskell ai primi anni significa che non devono disimparare lo stile imperativo. Haskell può anche produrre un codice molto conciso che le persone che avevano già un po 'di Java possono apprezzare.

Alcuni problemi che ho notato spesso hanno degli studenti:

  • All'inizio la corrispondenza dei motivi può essere un po 'difficile. Inizialmente gli studenti hanno avuto dei problemi nel vedere come sono correlate la costruzione di valore e la corrispondenza dei modelli. Hanno anche avuto alcuni problemi nel distinguere tra astrazioni. I nostri esercizi includevano funzioni di scrittura che semplificano l'espressione aritmetica e alcuni studenti hanno avuto difficoltà a vedere la differenza tra la rappresentazione astratta (ad esempio, Const 1 ) e la rappresentazione in meta-lingua ( 1 ) .

    Inoltre, se i tuoi studenti devono scrivere da soli le funzioni di elaborazione dell'elenco, fai attenzione a sottolineare la differenza tra i modelli

    []
    [x]
    (x:xs)
    [x:xs]
    

    A seconda di quanta programmazione funzionale vuoi insegnare loro lungo la strada, potresti semplicemente dare loro alcune funzioni di libreria e lasciarli giocare con quello.

  • Non abbiamo insegnato ai nostri studenti funzioni anonime, abbiamo semplicemente parlato loro delle clausole where . Per alcune attività questo era un po 'prolisso, ma altrimenti ha funzionato bene. Inoltre non abbiamo parlato loro di applicazioni parziali; questo è probabilmente abbastanza facile da spiegare in Haskell (a causa della sua forma di tipi di scrittura), quindi potrebbe valere la pena mostrarli.

  • Hanno rapidamente scoperto le comprensioni degli elenchi e le hanno preferite rispetto a funzioni di ordine superiore come filter , map , zipWith .

  • Penso che ci siamo persi un po 'nell'insegnare loro come far loro guidare i loro pensieri dai tipi. Non sono del tutto sicuro, tuttavia, se questo è utile per i principianti o meno.

  • I messaggi di errore di solito non sono molto utili per i principianti, a volte potrebbero aver bisogno di aiuto con questi. Non l'ho provato da solo, ma c'è un compilatore Haskell destinato in particolare ai nuovi arrivati, principalmente tramite migliori messaggi di errore: elio

  • Per i piccoli programmi, cose come possibili perdite di spazio non erano un problema.

Nel complesso, Haskell è una buona lingua di insegnamento, ma ci sono alcune insidie. Dato che gli studenti si sentono molto più a loro agio con la comprensione dell'elenco rispetto alle funzioni di ordine superiore, questo potrebbe essere l'argomento di cui hai bisogno. Non so quanto sia lungo il tuo corso o quanta programmazione vuoi insegnare loro, ma pianifico un po 'di tempo per insegnare loro concetti di base - ne avranno bisogno.

A proposito,

  

# SML ha un aspetto veramente interattivo   interprete in cui le funzioni possono essere   sia definito che usato. A Haskell,   le funzioni devono essere definite in a   file separato e compilato prima   utilizzato nella shell interattiva.

È impreciso. Usa GHCi:

Prelude> let f x = x ^ 2
Prelude> f 7
49
Prelude> f 2
4

Ci sono anche buone risorse per Haskell nell'educazione su haskell.org edu. pagina, con esperienze di diversi insegnanti. http://haskell.org/haskellwiki/Haskell_in_education

Infine, sarai in grado di insegnare loro il parallelismo multicore solo per divertimento, se usi Haskell :-)

Molte università insegnano Haskell come primo linguaggio funzionale o addirittura come primo linguaggio di programmazione, quindi non credo che questo sarà un problema.

Dopo aver tenuto alcuni degli insegnamenti in uno di questi corsi, non sono d'accordo sul fatto che le possibili confusioni che identifichi siano così probabili. Le fonti più probabili di confusione precoce sono l'analisi degli errori causati da un layout errato e messaggi misteriosi sulle classi di tipi quando i letterali numerici vengono utilizzati in modo errato.

Non sarei nemmeno d'accordo con qualsiasi suggerimento che Haskell non sia raccomandato per i principianti che iniziano con FP. È certamente l'approccio del big bang in modi in cui i linguaggi rigidi con mutazione non lo sono, ma penso che sia un approccio molto valido.

  
      
  • SML ha un interprete veramente interattivo in cui le funzioni possono essere definite e utilizzate. In Haskell, le funzioni devono essere definite in un file separato e compilate prima di essere utilizzate nella shell interattiva.
  •   

Sebbene gli Hug possano avere questa limitazione, GHCi non lo fa:

$ ghci
GHCi, version 6.10.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
Prelude> let hello name = "Hello, " ++ name
Prelude> hello "Barry"
"Hello, Barry"

Ci sono molte ragioni per cui preferisco GHC (i) a Hugs, questo è solo uno di questi.

  
      
  • SML fornisce una conferma esplicita dell'argomento della funzione e restituisce i tipi in una sintassi che è facile da capire. Ad esempio: val foo = fn: int * int - > Int. La sintassi implicita del curry di Haskell è un po 'più ottusa, ma non totalmente aliena. Ad esempio: foo :: Int - > Int - > Int.
  •   

SML ha quello che chiami "curry implicito" sintassi pure.

$ sml
Standard ML of New Jersey v110.69 [built: Fri Mar 13 16:02:47 2009]
- fun add x y = x + y;
val add = fn : int -> int -> int
  

In sostanza, SML e Haskell sono approssimativamente equivalenti. Mi rivolgo a Haskell perché adoro la comprensione delle liste e le liste infinite in Haskell. Ma sono preoccupato che il vasto numero di simboli nella sintassi compatta di Haskell potrebbe causare problemi agli studenti. Da quello che ho raccolto leggendo altri post su SO, Haskell non è raccomandato per i principianti che iniziano con FP. Ma non costruiremo applicazioni a tutti gli effetti, solo provando semplici algoritmi.

Mi piace usare Haskell molto più di SML, ma vorrei comunque insegnare prima a SML.

  • Secondo i pensieri di nominolo, le comprensioni dell'elenco do sembrano rallentare gli studenti dall'arrivare ad alcune funzioni di ordine superiore.
  • Se vuoi pigrizia e liste infinite, è istruttivo implementarlo esplicitamente.
  • Poiché SML viene valutato con entusiasmo, il modello di esecuzione è molto più semplice da comprendere e "debug tramite printf" funziona molto meglio che in Haskell.
  • Anche il sistema di tipi di SML è più semplice. Anche se la tua classe probabilmente non li userebbe comunque, le macchine da scrivere di Haskell sono ancora un dosso in più da superare: far loro capire la distinzione 'a rispetto a ' 'a in SML è abbastanza difficile.

La maggior parte delle risposte erano tecniche, ma penso che dovresti considerarne almeno una che non lo è: Haskell (come OCaml), in questo momento, ha una comunità più grande che la utilizza in una più ampia gamma di contesti. C'è anche un grande database di librerie e applicazioni scritte a scopo di lucro e divertimento su Hackage . Questo potrebbe essere un fattore importante nel mantenere alcuni dei tuoi studenti che usano la lingua dopo che il corso è finito e magari provare altre lingue funzionali (come Standard ML) in seguito.

Sono sorpreso che non stia prendendo in considerazione OCaml e F # dato che rispondono a molte delle tue preoccupazioni. Gli ambienti di sviluppo sicuramente decenti e utili sono una priorità per gli studenti? SML è molto indietro e F # è molto più avanti di tutti gli altri FPL in questo senso.

Inoltre, sia OCaml che F # hanno una comprensione dell'elenco.

Haskell. Sono avanti nella mia classe di algos / teoria in CS a causa delle cose che ho imparato usando Haskell. È un linguaggio così completo e ti insegnerà un sacco di CS, semplicemente usandolo .

Tuttavia, SML è molto più facile da imparare. Haskell ha caratteristiche come strutture di valutazione e controllo pigre che lo rendono molto più potente, ma con il costo di una curva di apprendimento ripida (ish). SML non ha tale curva.

Detto questo, la maggior parte di Haskell stava disimparando cose da linguaggi meno scientifici / matematici come Ruby, ObjC o Python.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top