Il sistema di tipi di Haskell è un ostacolo alla comprensione della programmazione funzionale? [chiuso]


33

Sto studiando Haskell allo scopo di comprendere la programmazione funzionale, con l'aspettativa che applicherò le intuizioni che ottengo in altre lingue (principalmente Groovy, Python, JavaScript).

Ho scelto Haskell perché avevo l'impressione che fosse puramente funzionale e che non mi permettesse di fare affidamento sullo stato.

Non ho scelto di imparare Haskell perché ero interessato a navigare in un sistema di tipo estremamente rigido.

La mia domanda è questa: un sistema di tipo forte è un sottoprodotto necessario di un linguaggio funzionale estremamente puro o è una scelta progettuale indipendente da Haskell?


6
Se non si desidera digitare esplicitamente nulla, non è necessario digitare esplicitamente nulla. Haskell può dedurre i tipi da solo. E non è che avrai una singola variabile che potenzialmente memorizza due tipi incompatibili.
Anon.

4
@Non si, ma i tuoi elenchi devono essere omogenei. Fidati di me, questo genere di cose può interferire, anche con l'inferenza del tipo.
Eric Wilson,

13
@FarmBoy e cosa c'è che non va nell'uso di Maybe? Java ti fa davvero usare Forse su tutte le classi, che è la cosa strana da fare.
alternativa il

3
E se vuoi davvero usare un elenco eterogeneo puoi ovviamente usare tipi di dati algebrici.
alternativa il

1
@mathepic a questo punto abbiamo davvero perso la traccia della mia domanda originale, che era una domanda perfettamente valida.
Eric Wilson,

Risposte:


40

Credo che comprendere il sistema di tipi di Haskell sia un amplificatore per comprendere la programmazione funzionale.

La cosa sulla programmazione puramente funzionale è che in assenza di effetti collaterali, che ti permettono di fare implicitamente ogni sorta di cose, la programmazione puramente funzionale rende la struttura dei tuoi programmi molto più esplicita.

Haskell ti impedisce di spingere le cose sotto il tappeto, ti costringe a gestire esplicitamente la struttura del tuo programma e ti insegna una lingua per descrivere queste strutture: la lingua dei tipi. Comprendere i tipi, in particolare quelli ricchi come Haskell, ti renderà un programmatore migliore in qualsiasi lingua.

Se Haskell non fosse fortemente tipizzato, concetti come monadi, funzioni applicative e simili non sarebbero mai stati applicati alla programmazione.


2
Questa è una buona risposta, la mia aggiunta è che mentre il sistema dei tipi può sembrare insolito all'inizio, in seguito quando inizierai ad apprendere i concetti più avanzati vedrai che ci sono alcune cose che possono essere fatte solo grazie all'adesione a quel tipo sistema (aggiungere STM e dati paralleli all'elenco sopra). Le cose che sarebbero non principianti in altri sistemi di tipo si adattano naturalmente al sistema Haskell. Il mio consiglio: seguitelo per un po ', lasciatelo affondare nel tempo (non è un linguaggio "stipato").
anon

2
So che questa è una risposta super vecchia, ma in realtà non sono d'accordo. Penso che, per quanto esplicito possa essere qualcosa nella lingua, il sistema dei tipi, in particolare con monadi come State e Parsec, spazza una tonnellata di cose sotto il tappeto. Questo in realtà sta interferendo molto con la mia capacità di apprendere le librerie della lingua.
Savanni D'Gerinel,

4
@ SavanniD'Gerinel: Penso che in questa risposta "spingere le cose sotto il tappeto" non significhi aggiungere funzionalità implicite (cosa che Haskell fa in modo controllato, ad esempio attraverso le monadi, e che aiuta a ridurre la piastra di cottura), ma piuttosto consentire qualche pezzo di codice fare qualcosa che non ci si aspetta che faccia. Ad esempio: una funzione pura in Haskell non avrà mai effetti collaterali. Periodo. In molte altre lingue puoi prometterlo nella documentazione di una funzione, ma nulla nella tua lingua ti impedirà di ottenere alcuni effetti collaterali da qualche parte nel tuo codice.
Giorgio,

33

Il linguaggio funzionale più tipizzato in modo dinamico è probabilmente Scheme. Detto questo, il sistema di tipi di Haskell è un indicatore della sua purezza. Si tratta di "come si misura la purezza?". Il sistema di tipi di Haskell ti consente di isolare facilmente azioni impure IO. Per fare ciò, è necessario un sistema di tipo statico.

Ma supponiamo che il sistema di tipi di Haskell non abbia nulla a che fare con la programmazione funzionale. Sarebbe comunque l'altezza dell'hubris affermare che il sistema dei tipi non ti aiuterebbe in questo sforzo educativo. Il sistema di tipi di Haskell è ricco e complesso e tanto più interessante rispetto ai sistemi di tipi di C ++ e OCaml.

È un ostacolo? No, penso che sia un vantaggio. Prova a considerare come affrontare la pigrizia di Haskell senza IOper esempio.


8
+1 Il sistema di tipi di Haskell può essere tuo amico una volta che ti ci abitui.
Larry Coleman,

"Per fare ciò, è necessario un sistema di tipo statico". Veramente?
Jon Harrop,

1
"tanto più interessante rispetto ai sistemi di tipi di C ++ e OCaml". Hai studiato i moduli di ordine superiore di prima classe di OCaml e il sistema di oggetti dedotti strutturalmente tipizzati e le varianti polimorfiche?
Jon Harrop,

2
@JonHarrop o un sistema di effetti o un modo per misurare / valutare la purezza. Sì, ecco perché è interessante confrontarli. Scelte diverse rendono diverse lingue.
Logan Capaldo,

20

Clojure è tipizzato in modo dinamico e quasi puro come Haskell, quindi c'è una buona argomentazione sul fatto che il sistema di tipi di Haskell fosse più una scelta progettuale che un requisito assoluto. Entrambi hanno sicuramente i loro punti di forza, quindi potresti prendere in considerazione Clojure se davvero non ti piace la rigidità di Haskell (ma vedi sotto).

Quando ho iniziato a utilizzare Haskell per la prima volta, ho considerato il sistema di tipi fastidioso e l'ho tollerato solo a causa dell'inferenza del tipo. Ho presto scoperto che molti errori di tipo del compilatore si sono lamentati di cose che non avrebbero funzionato comunque anche se il compilatore me lo avesse permesso di fare (ad esempio usando accidentalmente map invece di concatMap). Ho quindi scoperto che i programmi che superavano il controllo del tipo erano generalmente corretti, o almeno vicini alla correzione. Ho anche avuto una fase pigra in cui ho fatto il refactoring cambiando un tipo di funzione e lasciando che il compilatore mi dicesse cos'altro doveva essere cambiato. Alla fine, mi sono reso conto che il sistema di tipi di Haskell era in realtà molto espressivo e ho iniziato a progettare i miei programmi attorno ai tipi. Questo è il Santo Graal di Haskell.


Un'altra cosa da notare: ho imparato la programmazione funzionale usando sia Scheme che Haskell nello stesso momento (il primo per una lezione e il secondo per divertimento). Ho scoperto che comprendere la ricorsione era molto più facile con il pattern-matching di Haskell che con ifs e conds in Scheme, che immagino riporti anche a Clojure.
Tikhon Jelvis,

@Larry Coleman: +1 per descrivere precisamente la mia esperienza con i sistemi di tipi: prima C ++, poi Ocaml e ora la mia lingua Felix. Sì, continuo a refactor inseguendo gli errori del compilatore.
Yttrill

8

Il sistema di tipi di Haskell è la chiave della sua capacità di isolare gli effetti dal codice puro. A meno che non sia possibile isolare gli effetti in un altro modo o rimuoverli completamente, un forte sistema di tipo statico è un requisito per la pura programmazione funzionale.

Haskell è un ottimo esempio di linguaggio con un sistema di tipo statico forte. Se desideri un'istruzione ampia e completa nell'informatica e nella progettazione del linguaggio di programmazione in particolare, Haskell sarebbe una scelta eccellente come una delle lingue che dovresti imparare.

Il sistema dei tipi non dovrebbe essere un grosso ostacolo. Le persone che programmano tendono, anche quando usano linguaggi dinamici, a seguire convenzioni di battitura che possono essere codificate usando il sistema di tipi di Haskell. Haskell presenta anche un'inferenza di tipo che allevia la verbosità rispetto a linguaggi come C ++ e Java. Quando ricevi un messaggio di errore, il compilatore ti dice solo in fase di compilazione cosa ti direbbe una lingua con tipi dinamici in fase di esecuzione.

L'opposto di un sistema di tipo dinamico è un sistema di tipo statico, non un sistema di tipo forte. Un sistema di tipo forte è l'opposto di un sistema di tipo debole.


1
Ad esempio, C è staticamente ma debolmente tipizzato. Hai tipi, ma è facile sovvertire completamente il sistema di tipi, giocare con le rappresentazioni specifiche della macchina sottostante ecc. Molti linguaggi tipizzati dinamicamente OTOH sono tipizzati in modo abbastanza forte: pochi cast impliciti, pochi modi (se ce ne sono) per sovvertire il sistema dei tipi.
Steve314

4

Ti dice subito quando commetti errori stupidi. Questo è utile Ho lavorato in Racket (Scheme) questo ultimo termine, e ci sono state diverse volte in cui ho passato un s-exp non analizzato in cui mi aspettavo un errore analizzato per alcune funzioni nel mio interprete, e si è presentato solo nel mio suite di test di medie dimensioni. Se avessi avuto qualche digitazione statica, sarebbe stato subito portato alla mia attenzione.

Naturalmente, gli errori logici non possono davvero essere colti dal sistema dei tipi, ma il numero di modi in cui è possibile rovinare è notevolmente ridotto.

Inoltre, l'inferenza del tipo consente di ignorare il sistema di tipi, se lo si desidera. È ancora lì, ma non richiede input attivi da parte tua. È ancora utile capire i tipi delle tue funzioni, ma il codice corretto funzionerà bene.

La purezza di Haskell è codificata nel suo sistema di tipi. La monade IO è un costrutto a livello di tipo che impedisce al codice impuro di perdere funzioni pure, quindi la purezza è garantita dal sistema di tipi.


8
Se pensi di poter ignorare il sistema di tipi di Haskell, penso che non hai codificato molto Haskell.
Eric Wilson,

Non ignorare tanto quanto ignorarlo tanto quanto digitare la funzione, caricarla in GHCi e procedere: t su di essa. Ma dovrai ancora cospargere alcune funzioni integrali o altre a volte.
Theo Belaire,

1
Tyr, anche con la deduzione del tipo, il 90% dell'uso e della codifica delle funzioni di Haskell sta facendo sì che le cose dannate si mescolino tra loro, il che richiede una comprensione del suo sistema di tipi e arcani messaggi di errore di battitura. Anche ": t" non è una soluzione magica, è solo il primo passo per capire come compilare il programma.
Andres F.

Bene, alcune parti sono disordinate, sono d'accordo. Penso davvero che le cose numeriche nel preludio potrebbero essere ripulite e riparate, perché così com'è, è un casino terribile. Ma la maggior parte degli aspetti funzionali chiave sono piuttosto puliti. map, filter, foldr / le altre divertenti funzioni funzionali funzionano abbastanza bene.
Theo Belaire,

2

Essere un linguaggio "funzionale" significa (a parte altre cose) che le funzioni sono oggetti di prima classe nel linguaggio.

Essere un linguaggio "puro" significa che le funzioni sono funzioni matematiche (al contrario delle procedure) - dato lo stesso input, producono sempre lo stesso output.

Un "linguaggio funzionale puro" è quello in cui entrambi sostengono. Non sono a conoscenza di un "puro- ly linguaggio funzionale".

Un sistema di tipo forte è uno modo pulito di avere un linguaggio puro ma pratico. I tipi aiutano il compilatore a capire le ottimizzazioni, oltre a garantire ulteriormente la correttezza. (Ma questo non è l'unico modo: il clojure è puro, ma non ha un sistema di tipi così forte come Haskell.)

Se il sistema dei tipi ti dà fastidio, ti suggerirei di provare un linguaggio più dinamico, come Scheme, o di utilizzare il sistema di inferenza dei tipi di Haskell.


0

Sì, il sistema dei tipi è una risorsa incredibile. Sarebbe molto difficile persino descrivere come funzionano le monadi o come funzionano alcuni combinatori senza il sistema dei tipi. Considera quanti tutorial su Haskell ti chiedono prima di considerare il tipo della funzione in questione con a: t in REPL. Questo semplicemente non è disponibile in una lingua tipizzata in modo dinamico. Certo, tutta la complessità del sistema di tipi è ancora lì. Una monade è ancora una monade. Ma la lingua ha deciso di lavarsi le mani e di non fornire alcun aiuto. Sei da solo, amico. Non sto bussando alle lingue tipizzate dinamicamente. Li amo molto. Lo schema è un elettroutensile per eccellenza. Ma noterai che quando parliamo di cose come le monadi in linguaggi dinamici, lo facciamo spesso inventiamo una notazioneper descrivere il tipo di procedure. Un programmatore funzionale combatterà con i tipi in un modo o nell'altro. Il controllo del tipo di Haskell ti dà solo buoni strumenti per imparare a farlo.

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.