Come si progettano i programmi in Haskell o altri linguaggi di programmazione funzionale?


52

Ho una certa esperienza in linguaggi di programmazione orientati agli oggetti come c # o ruby. So come progettare un programma in stile orientato agli oggetti, come creare classi e oggetti e come definire le relazioni tra loro. Conosco anche alcuni modelli di design.

In che modo le persone scrivono programmi funzionali? Come iniziano? Esistono modelli di progettazione per linguaggi funzionali? Metodologie come la programmazione estrema o lo sviluppo agile sono applicabili ai linguaggi funzionali?


Risposte:


24

Scrivo la mia risposta principalmente pensando a Haskell, anche se molti concetti si applicano ugualmente bene ad altri linguaggi funzionali come Erlang, Lisp (s) e ML. Alcuni addirittura si applicano (in una certa misura) a Ruby, Python, Perl e Javascript.

In che modo le persone scrivono programmi funzionali? Come iniziano?

Scrivendo funzioni. Quando si esegue la programmazione funzionale, si sta scrivendo maino si sta scrivendo una funzione di supporto. A volte il tuo obiettivo principale potrebbe essere quello di scrivere un tipo di dati con varie funzioni rilevanti che vi operano.

La programmazione funzionale è molto adatta sia agli approcci top-down che bottom-up. Haskell incoraggia fortemente a scrivere i tuoi programmi in un linguaggio di alto livello e quindi a definire semplicemente i dettagli del tuo progetto di alto livello. Vedi minimum, ad esempio:

minimum    :: (Ord a) => [a] -> a
minimum xs =  foldl1 min xs

La funzione per trovare l'elemento più piccolo in un elenco viene scritta semplicemente come un attraversamento dell'elenco, usando la funzione min per confrontare ciascun elemento con l'accumulatore o il valore minimo corrente.

Esistono modelli di progettazione per linguaggi funzionali?

Ci sono due cose che potrebbero essere equiparate a "modelli di progettazione", imho, funzioni di ordine superiore e monadi . Parliamo del primo. Le funzioni di ordine superiore sono funzioni che accettano altre funzioni come input o producono funzioni come output. Qualsiasi linguaggio funzionale generalmente rende pesante uso di map, filterefold(fold è spesso chiamato anche "ridurre"): tre funzioni di base di ordine superiore che applicano una funzione a un elenco in diversi modi. Questi sostituiscono la piastra della caldaia per gli anelli in un modo bellissimo. Passare funzioni come parametri è un vantaggio estremamente potente per la programmazione; molti "modelli di progettazione" possono essere realizzati in modo più semplice utilizzando le funzioni di ordine superiore, essendo in grado di crearne di proprie ed essere in grado di sfruttare la potente libreria standard, che è piena di utili funzioni.

Le monadi sono l'argomento "più spaventoso". Ma non sono poi così spaventosi. Il mio modo preferito di pensare alle monadi è di pensarle come avvolgere una funzione in una bolla e dare a quella funzione superpoteri (che funzionano solo all'interno della bolla). Potrei elaborare, ma il mondo non ha davvero bisogno di un'altra analogia monade. Quindi passerò ad esempi rapidi. Supponiamo che io voglia usare un "modello di progettazione" non deterministico. Voglio eseguire lo stesso calcolo per vari input diversi contemporaneamente. Non voglio scegliere solo un input, voglio sceglierli tutti. Questa sarebbe la monade lista:

allPlus2 :: [Int] -> [Int]
allPlus2 xs = do x <- xs
                 return (x + 2)

Ora, il modo idiomatico di eseguire ciò è in realtà map, ma per amor di illustrazione, puoi vedere come la monade della lista mi ha permesso di scrivere una funzione che sembra funzionare su un valore, ma dotata della superpotenza per lavorare su ogni elemento in una lista? Altre superpotenze includono fallimento, stato, interazione con il "mondo esterno" ed esecuzione parallela. Questi superpoteri sono molto potenti e la maggior parte dei linguaggi di programmazione consente alle funzioni con superpoteri di scatenarsi ovunque. La maggior parte delle persone afferma che Haskell non consente affatto questi superpoteri, ma in realtà, Haskell li contiene solo in monadi, quindi il loro effetto può essere limitato e osservato.

tl; dr Le funzioni e le monadi di ordine superiore di Grokking sono l'equivalente di Haskell ai modelli di progettazione di grokking. Dopo aver appreso questi concetti di Haskell, inizi a pensare che i "modelli di progettazione" siano per lo più soluzioni alternative economiche per simulare il potere di Haskell.

Metodologie come la programmazione estrema o lo sviluppo agile sono applicabili ai linguaggi funzionali?

Non vedo nulla che leghi queste strategie di gestione a nessun paradigma di programmazione. Come affermato da phynfo, la programmazione funzionale ti costringe praticamente a fare la decomposizione funzionale, rompendo un grosso problema in sottoproblemi, quindi i mini-pietre miliari dovrebbero essere un gioco da ragazzi. Esistono strumenti come QuickCheck e Zeno per testare o persino dimostrare le proprietà delle funzioni che scrivi.


"Potrei elaborare, ma il mondo non ha davvero bisogno di un'altra analogia monade." - Abbiamo sempre bisogno di più analogie per le monadi e la tua è una delle migliori che abbia mai visto.
Adam Gent,

1
Ottima risposta, ma penso che la tua discussione sui modelli di design sia un po 'fuorviante. Mentre non hai bisogno di modelli di design in stile OO / GOF in Haskell - in effetti sarebbe ridicolo tentarli - i modelli stessi sono semplicemente dei modi in cui una comunità comunica soluzioni ai tipi di problemi che si presentano ancora e ancora. La comunità di Haskell è ancora molto giovane, quindi non ci sono ancora molti schemi di cui parlare, ma se mi chiedessi esempi di schemi di Haskell, menzionerei cose come GADTs o FRP Arrowized.
rtperson,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.