Lingue di programmazione funzionale più pure? [chiuso]

20

Sono interessato a migliorare l'apprendimento della programmazione funzionale. Per fare ciò, sembra ovvio che dovrei costringermi a usare il linguaggio di programmazione funzionale più puro possibile. Quindi, sto qui chiedendo, più o meno, per un ordinamento di linguaggi di programmazione funzionale in base alla loro purezza.

Mi sembra che sarebbe più pratico imparare Lisp o Clojure (o Scheme, o Scala, ecc.), ma per quello che ho sentito di recente, Haskell sarebbe molto difficile da battere nell'insegnare principi di programmazione funzionale a qualcuno. Non ne sono ancora sicuro, quindi ti chiedo: che è il linguaggio di programmazione funzionale più puro? Un ordine sarebbe bello se molti fossero in competizione per il magnifico titolo del linguaggio di programmazione funzionale più puro.

    
posta Joanis 10.12.2010 - 05:24
fonte

7 risposte

26

Non esiste una scala per valutare il grado di purezza dei linguaggi funzionali. Se la lingua consente effetti collaterali è impura, altrimenti è pura. Con questa definizione, Haskell, Mercury, Clean ecc sono puri linguaggi funzionali; mentre Scala, Clojure, F #, OCaml ecc sono impure.

EDIT: Forse avrei dovuto formularlo come "se il linguaggio non consente effetti collaterali senza far sapere al sistema di tipi , è puro. Altrimenti è impuro".

    
risposta data 10.12.2010 - 05:36
fonte
15

Poiché l'apprendimento è il tuo obiettivo, e non scrivere programmi di per sé, non puoi ottenere più puramente di Calcolo Lambda .

Lambda Calculus era in circolazione prima dell'invenzione dei computer. Ci sono voluti diversi logici esperti che ci lavoravano per capire come eseguire la sottrazione (per un po 'è stato teorizzato che solo l'addizione e la moltiplicazione erano possibili).

Apprendi come booleani e numeri e if possono essere inventati da apparentemente nulla non metterà più benzina nel tuo serbatoio, ma renderà il tuo serbatoio molto più grande.

    
risposta data 10.12.2010 - 06:08
fonte
6

I linguaggi impuri non differiscono in linea di principio dai linguaggi imperativi più familiari, specialmente ora che sono stati copiati molti trucchi funzionali. Ciò che è diverso è lo stile: come risolvi i problemi.

Che contenga Haskell come puro o che contenga la monade IO come impurità, lo stile Haskell è una forma estrema di questo stile e vale la pena di essere studiato.

La monade Haskell IO è derivata dalla teoria matematica delle (ovviamente) monadi. Tuttavia, per i programmatori imperativi, penso che un modo arretrato di arrivare alle monadi abbia più senso.

Fase uno: un linguaggio puramente funzionale può facilmente restituire un valore di stringa grande come risultato. Questa grande stringa può essere il codice sorgente di un programma imperativo, derivato in modo puramente funzionale da alcuni parametri che specificano i requisiti. È quindi possibile creare un compilatore "di livello superiore" che esegue il generatore di codice, quindi alimenta automaticamente il codice generato nel compilatore del linguaggio imperativo.

Fase due: anziché generare un codice sorgente testuale, si genera un albero di sintassi astratto strongmente tipizzato. Il compilatore in linguaggio imperativo viene assorbito nel compilatore "di livello superiore" e accetta l'AST direttamente come codice sorgente. Questo è molto più vicino a quello che fa Haskell.

Questo è ancora imbarazzante, però. Ad esempio, hai due distinti tipi di funzioni: quelle valutate durante la fase di generazione del codice e quelle eseguite quando viene eseguito il programma generato. È un po 'come la distinzione tra funzioni e modelli in C ++.

Quindi, per la fase 3, rendi i due uguali: la stessa funzione con la stessa sintassi può essere parzialmente valutata durante la "generazione del codice", o completamente valutata, o non valutata affatto. Inoltre, eliminare tutti i nodi AST del costrutto di ciclo a favore della ricorsione. In effetti, scartare l'idea dei nodi AST come un tipo speciale di dati del tutto - non hanno nodi AST "valore letterale", ma solo valori ecc.

Questo è praticamente ciò che fa il monade IO - l'operatore di bind è un modo di comporre "azioni" per formare programmi. Non è niente di speciale - solo una funzione. Molte espressioni e funzioni possono essere valutate durante la "generazione del codice", ma quelle che dipendono dagli effetti collaterali I / O devono avere una valutazione ritardata fino all'ora di esecuzione, non da una regola speciale, ma come conseguenza naturale delle dipendenze dei dati in espressioni.

Le Monade in generale sono solo generalizzazioni: hanno la stessa interfaccia, ma implementano le operazioni astratte in modo diverso, quindi invece di valutare una descrizione del codice imperativo, valutano invece qualcos'altro. Avere la stessa interfaccia significa che ci sono alcune cose che puoi fare alle monadi senza preoccuparti di quale monade, che risulta essere utile.

Questa descrizione farà senz'altro esplodere le teste dei puristi, ma per me spiega alcuni dei veri motivi per cui Haskell è interessante. Sfoca il confine tra programmazione e metaprogrammazione e utilizza gli strumenti della programmazione funzionale per reinventare la programmazione imperativa senza richiedere una sintassi speciale.

Una critica che ho dei template C ++ è che sono una specie di sublocazione funzionale pura in un linguaggio imperativo - per valutare la stessa funzione di base in fase di compilazione piuttosto che in fase di esecuzione devi ri-implementarla usando un stile di codifica completamente diverso. In Haskell, mentre l'impurità deve essere etichettata come tale nel suo tipo, la stessa identica funzione può essere valutata sia in senso meta-programmazione che in senso run-time non-meta-programmazione nello stesso programma - non c'è una linea dura tra programmazione e metaprogrammazione.

Detto questo, ci sono alcune cose che metaprogrammano che Haskell standard non può fare, fondamentalmente perché i tipi (e forse poche altre cose) non sono valori di prima classe. Ci sono varianti linguistiche che cercano di affrontare questo, però.

Molte delle cose che ho detto su Haskell possono essere applicate in lingue funzionali impure - e talvolta anche in lingue imperative. Haskell è diverso perché non hai altra scelta che seguire questo approccio: in pratica ti costringe a imparare questo stile di lavoro. Puoi "scrivere C in ML", ma non puoi "scrivere C in Haskell" - almeno non senza imparare cosa sta succedendo sotto il cofano.

    
risposta data 15.06.2011 - 05:26
fonte
4

Personalmente categorizzo le lingue in tre livelli di purezza funzionale:

  • Linguaggi funzionali puri - ovvero quelli che trattano l'intero programma come una pura funzione e gestiscono la mutabilità solo attraverso l'interazione con il runtime - Haskell è probabilmente il canonico esempio

  • Impure lingue funzionali - ovvero quelle che enfatizzano uno stile funzionale ma consentono effetti collaterali. Clojure è chiaramente in questa categoria (consente la mutazione in modo controllato come parte del suo framework STM), anche OCaml o F #

  • linguaggi multi-paradigma - questi non sono i linguaggi funzionali in primo luogo, ma possono supportare uno stile funzionale mediante l'uso di funzioni di prima classe, ecc. Scala è un buon esempio qui, metterei anche Common Lisp in questa categoria e potresti persino includere linguaggi come JavaScript .

Nella tua situazione, suggerirei di imparare prima Haskell, poi Clojure. Questo è quello che ho fatto e ha funzionato molto bene per me! Haskell è bello e ti insegna i più puri principi funzionali, Clojure è molto più pragmatico e ti aiuta a fare molto mentre sei ancora molto funzionale nel cuore.

In realtà non considero la terza categoria come linguaggi funzionali (sebbene dopo aver appreso Haskell e Clojure mi trovo spesso a sfruttare le tecniche funzionali quando li uso!)

    
risposta data 15.06.2011 - 00:42
fonte
3

Se un puro linguaggio funzionale è tale, che ha solo funzioni pure (routine che non hanno effetti collaterali), allora è un po 'inutile, perché non può leggere input o scrivere output;)

Poiché questo è davvero per l'apprendimento, penso che l'isolamento non sia necessariamente il modo di procedere. La programmazione funzionale è un paradigma. È importante capire quali sono i paradigmi adatti a quali problemi e, soprattutto, come possono essere combinati al meglio.

I'm going to say it now: programming fashions are stupid and counterproductive. The only things that matter are that your program is short, easy to write, easy to maintain and works correctly. How you achieve this has nothing to do with programming fads. - Richard Jones

Oltre a questo, se stai cercando "purezza" potresti dare un'occhiata a Pure . Nota comunque, l'estrema facilità con cui si chiamano le routine C lo rende funzionalmente impuro (ma anche molto potente).

    
risposta data 15.06.2011 - 01:03
fonte
3

Non una risposta completamente seria, ma Unlambda deve essere un concorrente. Non è possibile ottenere più "puramente funzionali" rispetto ai combinatori S K I.

    
risposta data 15.06.2011 - 07:19
fonte
2

Erlang, Haskell, Scheme, Scala, Clojure e F #

Questa domanda probabilmente ti aiuterà meglio nella tua ricerca come bene .

    
risposta data 10.12.2010 - 05:35
fonte

Leggi altre domande sui tag