"Linguaggio puramente funzionale" è un termine abbastanza confuso. Preso alla lettera, il termine significa qualcosa come "un linguaggio che è solo funzionale e nient'altro". Quindi comprende Haskell, ML, Clean, ecc .; Lo schema si avvicina ma non ce la fa; e i linguaggi funzionali "impuri" sono rigorosamente Perl, Scala, JavaScript, ecc. - Lingue "multi-paradigma" con un buon supporto per la programmazione funzionale. Questo chiaramente non è ciò che la gente intende per "puramente funzionale", però.
La chiave è capire che le persone che dicono "linguaggio puramente funzionale" intendono davvero dire "linguaggio funzionale puro" --- un linguaggio basato su pure funzioni --- e "puramente funzionale" è un lapsus che è diventare convenzionale. Il motto è "sono le funzioni che sono pure, non la lingua".
Ora, ovviamente non puoi fare I / O con pure funzioni 1 . Ciò rende i linguaggi puramente funzionali diversi dai linguaggi impuri, in cui una funzione come (semantica inventata)
promptForName = do { print "What is your name"; getLine }
potrebbe essere attribuito il tipo String -> String
. Ma un linguaggio funzionale avrà generalmente molti altri tipi oltre alle sole funzioni! ("Puramente funzionale" non significa "tutto è una funzione" nello stesso modo in cui " OO puro "significa" tutto è un oggetto ".) È possibile utilizzare qualsiasi di questi tipi per eseguire I / O, se questo è ciò che si desidera per tale tipo.
Quindi la monade IO in Haskell è solo un tipo di dati. Un valore di quel tipo rappresenta un elenco di azioni I / O per il programma da eseguire (in pratica). In fase di runtime, il computer si alterna tra la valutazione di tale elenco e l'esecuzione delle azioni descritte. Ma la valutazione non ha I / O! Succede dopo il valore è già stato ottenuto.
1 Senza definire semantica aggiuntiva. Potresti dire "un programma è una funzione di tipo String -> String
; eseguirlo legge i contenuti di STDIN come una stringa (pigra), applica la funzione a quella stringa e scrive il risultante (pigro) stringa su STDOUT, ma il punto di ingresso è la funzione solo di tipo String -> String
nel programma che ha quella semantica, quindi non è veramente il tipo di funzione che esegue l'I / O qui.