Un linguaggio di programmazione che non consente l'IO. Haskell non è un linguaggio puro

7

Ci sono lingue pure al 100% (come descrivo in il post di Overflow dello stack ) già disponibile e, in caso affermativo, potrebbero essere utilizzati per fare effettivamente cose? cioè hanno un'implementazione? Non sto cercando matematica cruda su carta / calcolo lambda puro. Tuttavia il calcolo lambda puro con un compilatore o un sistema runtime allegato è qualcosa di cui sarei interessato a conoscere.

    
posta TheIronKnuckle 22.11.2011 - 09:28
fonte

6 risposte

20

In effetti, come affermava una volta Simon Peyton Jones, Haskell è la lingua imperativa migliore là fuori.

Seriamente, la purezza non è un problema religioso. Il problema non è che esistono funzioni impure e dati mutabili. I problemi nei linguaggi convenzionali sono che spesso non si può dire impuro puro e mutabile da immutabile: non guardandolo, non compilandolo, solo eseguendolo.

Questo è il grande vantaggio di Clean, Haskell (e follower come Frege ). Al contrario, linguaggi come F #, Scala o Clojure che abbracciano il mondo imperativo e aggiungono semplicemente la possibilità di costruire qualcosa di funzionale, affliggono gli stessi problemi delle lingue imperative, sebbene possano sembrare davvero molto pratici.

    
risposta data 22.11.2011 - 10:32
fonte
9

Mi sembra che tu stia cercando di reinventare Haskell.

The language doesn't need to have side effects at all. The run-time system does. The compiler/run-time system simply needs to search for the main function and treat it as an entry-point to the program as a whole.

Bella descrizione di come viene eseguito l'I / O in Haskell.

Hell, maybe you could execute until you need to prompt the user, wrap up the remainder of the code as a completely new program in the return type

Intendi monadi?

>>= :: M a -> (a -> M b)

Dopo che la prima metà (M a) ha richiesto all'utente di fornire dati (di tipo a), la seconda metà (a - > M b) è il "resto" che descrivi.

Se Haskell ti permettesse di introspettare le funzioni invece di permetterti di eseguirle, sarebbe anche omoiconico.

    
risposta data 22.11.2011 - 13:35
fonte
6

Considererei Haskell puro al 100%. E sicuramente può fare qualcosa.

Anche se ci sono dei bei dibattiti su cosa sia in realtà "100% puro", non è certamente vero che un linguaggio funzionale puro non può fare IO. Consulta anche le domande frequenti su comp.lang.functional .

Tutto quello che devi fare per consentire l'IO in un linguaggio puro è passare un parametro che rappresenta lo stato del mondo per il programma e restituire lo stato del mondo come output. Questo programma non ha effetti collaterali, è referenzialmente trasparente e conta come puro al 100%. Questo è praticamente ciò che l'IO Monad di Haskell fa sotto il cofano.

Una menzione speciale forse per Clojure, che è sicuramente un linguaggio pratico con l'intero ecosistema JVM e la toolchain a portata di mano. Chiaramente non è puro al 100% (dal momento che è possibile ottenere effetti collaterali tramite i riferimenti gestiti STM, varie funzioni IO o l'interoperabilità Java). Tuttavia, il linguaggio principale se si evitano questi casi speciali è puramente funzionale. Quindi, se ti attieni al puro sottoinsieme di Clojure, per la maggior parte degli scopi hai effettivamente un linguaggio puramente funzionale e discreto.

    
risposta data 22.11.2011 - 11:29
fonte
4

Un linguaggio "puro" che non poteva fare IO non poteva fare molto. ... dopotutto, anche stampando un risultato sullo schermo è IO. Quindi, se non riesci a vedere il risultato di un programma, non sarebbe piuttosto inutile?

Non è stato possibile leggere i file, non è stato possibile ascoltare i socket, non è possibile interagire con gli utenti, non è stato possibile chiedere input ... ecc. Che cosa sarebbe bello?

Detto questo, Haskell è il più vicino a "puro" (qualunque cosa significhi) programmazione funzionale che io conosca. Il loro intero IO-sistema è persino realizzato usando Monads, che è un mix tra IO e funzionale.

So anche di "Clean", che è un linguaggio funzionale accademico e vede IO come una trasformazione di un oggetto Mondo se ricordo bene ... tuttavia, questo inizia ad essere molto esotico.

    
risposta data 22.11.2011 - 10:31
fonte
1

"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.

    
risposta data 02.12.2015 - 01:50
fonte
1

Puoi consultare lingue reattive sincrone come Lustre o Segnale , per esempio. Si tratta di linguaggi dedicati alla specifica dei sistemi reattivi incorporati, basati sulla programmazione del flusso di dati.

Definisci funzioni che operano su valori nel tempo. Queste funzioni possono contenere uno stato, nel qual caso sono chiamati nodi . In Signal, nodes e funzioni sono diversi tipi di processi . Ma il modo in cui lo stato è definito fa riferimento ai valori precedenti delle variabili di flusso.

Quindi potresti ad esempio codificare una macchina a stati avendo una variabile di stato interna. Ad ogni timestep, il nuovo stato è definito come una (pura) funzione degli ingressi correnti e dello stato precedente.

Quando si tratta di compilare quelle lingue, ad es. C, ottieni variabili globali che vengono sovrascritte all'interno di un ciclo big for (l'apparente antitesi della pura programmazione funzionale), ma in realtà è perfetto in un contesto in cui è richiesta l'allocazione della memoria statica e l'esecuzione deterministica del runtime.

    
risposta data 22.03.2016 - 21:11
fonte

Leggi altre domande sui tag