Domanda

Al secondo anno di università ci hanno "insegnato" Haskell, non ne so quasi nulla e ancor meno della programmazione funzionale.

Cos'è la programmazione funzionale, perché e/o dove vorrei usarla invece della programmazione non funzionale e ho ragione nel pensare che C sia un linguaggio di programmazione non funzionale?

È stato utile?

Soluzione

Una caratteristica fondamentale di un linguaggio funzionale è il concetto di funzioni di prima classe.L'idea è che puoi passare funzioni come parametri ad altre funzioni e restituirle come valori.

La programmazione funzionale prevede la scrittura di codice che non cambia stato.Il motivo principale per farlo è che le chiamate successive a una funzione produrranno lo stesso risultato.Puoi scrivere codice funzionale in qualsiasi linguaggio che supporti funzioni di prima classe, ma ci sono alcuni linguaggi, come Haskell, che non ti consentono di cambiare stato.In effetti, non dovresti avere alcun effetto collaterale (come la stampa di testo), il che sembra che potrebbe essere completamente inutile.

Haskell utilizza invece un approccio diverso all'IO:monadi.Questi sono oggetti che contengono l'operazione IO desiderata che deve essere eseguita dal livello superiore dell'interprete.A qualsiasi altro livello sono semplicemente oggetti nel sistema.

Quali vantaggi offre la programmazione funzionale?La programmazione funzionale consente di codificare con meno potenziali bug perché ogni componente è completamente isolato.Inoltre, l'uso della ricorsione e delle funzioni di prima classe consente semplici prove di correttezza che tipicamente rispecchiano la struttura del codice.

Altri suggerimenti

Cos'è la programmazione funzionale

Esistono due diverse definizioni di "programmazione funzionale" di uso comune oggi:

La definizione più vecchia (originariamente da Lisp) è che la programmazione funzionale riguarda la programmazione utilizzando funzioni di prima classe, ovverodove le funzioni sono trattate come qualsiasi altro valore in modo da poter passare funzioni come argomenti ad altre funzioni e la funzione può restituire funzioni tra i loro valori restituiti.Ciò culmina nell'uso di funzioni di ordine superiore come map E reduce (forse ne hai sentito parlare mapReduce come un'unica operazione molto utilizzata da Google e, non sorprende, che sia un parente stretto!).I tipi .NET System.Func E System.Action rendere disponibili funzioni di ordine superiore in C#.Sebbene il currying non sia pratico in C#, le funzioni che accettano altre funzioni come argomenti sono comuni, ad es.IL Parallel.For funzione.

La definizione più recente (resa popolare da Haskell) è che la programmazione funzionale riguarda anche la minimizzazione e il controllo degli effetti collaterali, inclusa la mutazione, ad es.scrivere programmi che risolvono problemi componendo espressioni.Questa è più comunemente chiamata "programmazione puramente funzionale".Ciò è reso possibile da approcci estremamente diversi alle strutture dati chiamate "strutture dati puramente funzionali".Un problema è che la conversione degli algoritmi imperativi tradizionali in strutture di dati puramente funzionali in genere peggiora le prestazioni 10 volte.Haskell è l'unico linguaggio di programmazione puramente funzionale sopravvissuto, ma i concetti si sono insinuati nella programmazione tradizionale con librerie simili Linq sulla rete.

dove vorrei usarlo invece della programmazione non funzionale

Ovunque.I lambda in C# hanno ora dimostrato importanti vantaggi.C++11 ha lambda.Non ci sono scuse per non utilizzare funzioni di ordine superiore ora.Se puoi utilizzare un linguaggio come F#, trarrai vantaggio anche dall'inferenza del tipo, dalla generalizzazione automatica, dal currying e dall'applicazione parziale (oltre a molte altre funzionalità del linguaggio!).

ho ragione nel pensare che C sia un linguaggio di programmazione non funzionale?

SÌ.Il C è un linguaggio procedurale.Tuttavia, è possibile ottenere alcuni vantaggi della programmazione funzionale utilizzando i puntatori a funzione e void * in C.

Potrebbe valere la pena dare un'occhiata a questo articolo Fa# "101" su CoDe Mag recentemente pubblicato.

Anche, Dustin Campbell ha un blog fantastico dove ha pubblicato molti articoli sulle sue avventure su come mettersi al passo con F#..

Spero che li trovi utili :)

MODIFICARE:

Inoltre, giusto per aggiungere, la mia comprensione della programmazione funzionale è questa qualunque cosa è una funzione, o parametri di una funzione, piuttosto che istanze/oggetti con stato.Ma potrei sbagliarmi F# è qualcosa in cui muoio dalla voglia di entrare ma non ho tempo!:)

Il codice di esempio di John the Statistician non mostra la programmazione funzionale, perché quando si esegue la programmazione funzionale, la chiave è che il codice NON esegue ASSEGNAZIONI ( record = thingConstructor(t) è un compito) e NON HA EFFETTI COLLATERALI (localMap.put(record) è un'affermazione con un effetto collaterale).Come risultato di questi due vincoli, tutto ciò che a funzione fa è completamente catturato dai suoi argomenti e dal suo valore restituito.Riscrivere il codice dello statistico come dovrebbe apparire, se si volesse emulare un linguaggio funzionale utilizzando C++:

RT getOrCreate(const T thing, 
                  const Function<RT<T>> thingConstructor, 
                  const Map<T,RT<T>> localMap) {
    return localMap.contains(t) ?
        localMap.get(t) :
        localMap.put(t,thingConstructor(t));
}

Come risultato della regola senza effetti collaterali, ogni affermazione fa parte del valore restituito (quindi return arriva Primo), e ogni affermazione è un'espressione.Nei linguaggi che impongono la programmazione funzionale, il return la parola chiave è implicita e il file Se si comporta come quella del C++ ?: operatore.

Inoltre, tutto è immutabile, quindi localMap.put deve creare una nuova copia di localMap e restituirlo, invece di modificare l'originale localMap, come farebbe un normale programma C++ o Java.A seconda della struttura di localMap, la copia potrebbe riutilizzare i puntatori nell'originale, riducendo la quantità di dati da copiare.

Alcuni dei vantaggi della programmazione funzionale includono il fatto che i programmi funzionali sono più brevi, ed è più facile modificare un programma funzionale (perché non ci sono effetti globali nascosti da tenere in considerazione), ed è più facile inserire il programma direttamente nel contesto. primo posto.

Tuttavia, i programmi funzionali tendono a essere eseguiti lentamente (a causa di tutte le copie che devono fare) e tendono a non interagire bene con altri programmi, processi del sistema operativo o sistemi operativi che gestiscono indirizzi di memoria, little-endian blocchi di byte e altri bit non funzionali specifici della macchina.Il grado di noninteroperabilità tende ad essere inversamente correlato al grado di purezza funzionale e al rigore del sistema tipo.

I linguaggi funzionali più popolari hanno sistemi di tipi davvero molto rigidi.In OCAML, non è nemmeno possibile mischiare numeri interi e numeri in virgola mobile, o utilizzare gli stessi operatori (+ serve per sommare numeri interi, +.serve per aggiungere float).Questo può essere un vantaggio o uno svantaggio, a seconda di quanto apprezzi la capacità di un controllo di tipo di individuare determinati tipi di bug.

Anche i linguaggi funzionali tendono ad avere ambienti di runtime molto grandi.Haskell è un'eccezione (gli eseguibili GHC sono piccoli quasi quanto i programmi C, sia in fase di compilazione che in fase di esecuzione), ma i programmi SML, Common Lisp e Scheme richiedono sempre tonnellate di memoria.

Sì, hai ragione nel pensare che il C sia un linguaggio non funzionale.Il C è un linguaggio procedurale.

Preferisco utilizzare la programmazione funzionale per risparmiarmi lavoro ripetuto, creando una versione più astratta e poi utilizzando quella al suo posto.Vorrei fare un esempio.In Java, mi ritrovo spesso a creare mappe per registrare strutture e quindi a scrivere strutture getOrCreate.

SomeKindOfRecord<T> getOrCreate(T thing) { 
    if(localMap.contains(t)) { return localMap.get(t); }
    SomeKindOfRecord<T> record = new SomeKindOfRecord<T>(t);
    localMap = localMap.put(t,record);
    return record; 
}

Questo accade molto spesso.Ora, in un linguaggio funzionale, potrei scrivere

RT<T> getOrCreate(T thing, 
                  Function<RT<T>> thingConstructor, 
                  Map<T,RT<T>> localMap) {
    if(localMap.contains(t)) { return localMap.get(t); }
    RT<T> record = thingConstructor(t);
    localMap = localMap.put(t,record);
    return record; 
}

e non avrei mai più dovuto scriverne uno nuovo, potrei ereditarlo.Ma potrei farne uno migliore dell'ereditarietà, potrei dire nel costruttore di questa cosa

getOrCreate = myLib.getOrCreate(*,
                                SomeKindOfRecord<T>.constructor(<T>), 
                                localMap);

(dove * è una sorta di notazione "lascia questo parametro aperto", che è una sorta di strigliatura)

e quindi il getOrCreate locale è esattamente lo stesso che sarebbe stato se avessi scritto tutto, in una riga, senza dipendenze di ereditarietà.

Se stai cercando un buon testo su F#

Esperto Fa# è co-scritto da Don Syme.Creatore di Fa#.Ha lavorato sui generici in .NET appositamente per poter creare F#.

F# è modellato su OCaml, quindi qualsiasi testo OCaml ti aiuterà a imparare anche F#.

io trovo Cos'è la programmazione funzionale? per essere utile

La programmazione funzionale riguarda la scrittura di funzioni pure, la rimozione input e output nascosti per quanto possibile, in modo che la maggior parte dei nostri il codice il più possibile descrive solo una relazione tra input e Uscite.

Preferisco esplicito when param

public Program getProgramAt(TVGuide guide, int channel, Date when) {
  Schedule schedule = guide.getSchedule(channel);

  Program program = schedule.programAt(when);

  return program;
}

Sopra

public Program getCurrentProgram(TVGuide guide, int channel) {
  Schedule schedule = guide.getSchedule(channel);

  Program current = schedule.programAt(new Date());

  return current;
}

Un linguaggio funzionale è attivamente ostile agli effetti collaterali.Gli effetti collaterali sono la complessità e la complessità sono i bug e i bug sono il diavolo.Un linguaggio funzionale ti aiuterà anche a essere ostile agli effetti collaterali.

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