Ci sono aspetti negativi o problemi con Haskell?


47

Sto cercando di immergermi in Haskell per il mio prossimo (relativamente banale) progetto personale. I motivi per cui sto affrontando Haskell sono:

  1. Metti la mia testa in un linguaggio puramente funzionale
  2. Velocità. Mentre sono sicuro che questo può essere discusso, profilando che ho visto le unghie di Haskell vicine al C ++ (e sembra essere un po 'più veloce di Erlang).
  3. Velocità. Il web server Warp sembra essere pazzo velocemente rispetto a praticamente tutto il resto .

Quindi, dato questo, quello che sto cercando sono gli svantaggi o i problemi che si presentano con Haskell. Il web ha un'enorme quantità di informazioni sul perché Haskell è una buona cosa, ma non ho trovato molti argomenti sul suo lato brutto (a parte le lamentele sulla sua sintassi di cui non mi interessa affatto).

Un esempio di ciò che sto cercando potrebbe essere come GIL di Python. Qualcosa che non ha sollevato la testa fino a quando non ho davvero iniziato a guardare la concorrenza in un ambiente CPython.



26
Ho sentito che programmatori minori hanno affrontato problemi di fusione del cervello. È una condizione molto costosa da trattare.
ChaosPandion,

1
@FrustratedWithFormsDesigner: Grazie per il link. Tuttavia, non c'è ancora alcun riferimento ad alcun aspetto negativo tecnico di Haskell .. Potrebbe essere non ce ne sono ? ;)
Demian Brecht,

6
@ChaosPandion: Ho sentito lo stesso .. Ma se non fondere il cervello, stanno in realtà cercando ? ;) Inoltre, non mi considererei davvero un programmatore minore, quindi non sono eccessivamente preoccupato per questo;)
Demian Brecht,

3
@ChaosPandion: e la maggior parte dei piani sanitari non lo copre. :(
FrustratedWithFormsDesigner

Risposte:


48

Alcuni aspetti negativi che mi vengono in mente:

  • A causa della natura della lingua e delle sue solide radici nel mondo accademico, la comunità ha una mentalità molto matematica; se sei una persona pragmatica, a volte può essere travolgente e se non parli il gergo, avrai un momento più difficile che con molte altre lingue.
  • Mentre esiste un'incredibile ricchezza di biblioteche, la documentazione è spesso concisa.
  • I tutorial delicati per principianti sono pochi e difficili da trovare, quindi la curva di apprendimento iniziale è piuttosto ripida.
  • Alcune funzionalità linguistiche sono inutilmente goffe; un esempio importante è il modo in cui la sintassi dei record non introduce un ambito di denominazione, quindi non c'è modo di avere lo stesso nome di campo del record in due tipi diversi all'interno dello stesso spazio dei nomi del modulo.
  • Per impostazione predefinita, Haskell assume una valutazione pigra e, sebbene questa sia spesso un'ottima cosa, a volte può morderti in modi cattivi. Usare la valutazione pigra in modo ingenuo in situazioni non banali può portare a colli di bottiglia di prestazioni non necessarie e capire cosa sta succedendo sotto il cofano non è esattamente semplice.
  • Una valutazione pigra (specialmente combinata con la purezza e un compilatore aggressivamente ottimizzante) significa anche che non si può facilmente ragionare sull'ordine di esecuzione; in effetti, non sai nemmeno se un determinato codice viene effettivamente valutato in una determinata situazione. Di conseguenza, il debug del codice Haskell richiede una mentalità diversa, se non altro perché passare attraverso il codice è meno utile e meno significativo.
  • A causa della purezza di Haskell, non è possibile utilizzare effetti collaterali per eseguire operazioni come l'I / O; devi usare una monade e 'abusare' della valutazione pigra per raggiungere l'interattività e devi trascinare il contesto monadico ovunque tu voglia fare I / O. (Questa è in realtà una buona funzionalità in molti modi, ma a volte rende impossibile la codifica pragmatica.)

16
In realtà ci sono alcuni libri introduttivi davvero buoni disponibili gratuitamente online adesso. Learn You a Haskell for Great Good è uno dei migliori libri di programmazione per principianti che abbia mai letto e Real World Haskell è una grande risorsa intermedia.
Tikhon Jelvis,

1
@TikhonJelvis: Quelli sono davvero gli unici due candidati che ho trovato degno di essere usato; "Learn You A Haskell" mi ha confuso più di ogni altra cosa, "Real World Haskell" ha funzionato per me, ma presuppone un po 'di background di programmazione. C'è anche "Gentle Introduction to Haskell", ma è quasi gentile, soprattutto se non hai un background in matematica.
martedì

Uso "Gentle Introduction to Haskell" e "Real World Haskell". La combinazione dei due mi ha dato molte informazioni utili. Sono a un livello in cui sono pronto per un progetto non banale ma sfortunatamente non ho molto tempo per farlo.
Giorgio,

9
"se sei una persona pragmatica ...": a volte usare un linguaggio orientato alla matematica può essere una decisione molto pragmatica se ti evita di correggere un sacco di bug in seguito. Ovviamente, dovresti sempre trovare un equilibrio tra quanto tempo risparmi utilizzando uno strumento e quanto tempo extra devi imparare per usarlo.
Giorgio,

Le monadi funzionerebbero (e funzionerebbero in altre lingue) allo stesso modo in un linguaggio rigoroso. Non devi assolutamente "abusare" della valutazione pigra per raggiungere l'interattività, è banale scrivere un rigido programma interattivo in Haskell.
punto

19

La maggior parte degli aspetti negativi di Haskell (così come la maggior parte degli aspetti positivi di Haskell) derivano dalle sue due caratteristiche distintive: è pigro e puramente funzionale.

Essere pigri rende più difficile ragionare sulle prestazioni. Soprattutto per le persone che non sono abituate alla pigrizia, ma anche per gli Haskeller esperti può essere difficile vedere come la pigrizia influenzerà le prestazioni in alcuni casi.

Pigrizia significa anche che è più difficile creare benchmark precisi senza usare librerie come Criterion.

Essere puramente funzionali significa che ogni volta che è necessario utilizzare strutture di dati mutabili (nei casi in cui non è possibile ottenere le prestazioni desiderate senza di loro, anche se grazie all'ottimizzatore GHC che non si verifica tutte le volte che si potrebbe pensare), si sarà bloccato nella monade IO (o ST), il che rende il codice più ingombrante.

Dato che hai indicato la velocità come uno dei tuoi obiettivi, dovrei sottolineare che spesso ci sono enormi differenze nelle prestazioni tra il codice Haskell ottimizzato a mano e il codice Haskell che è stato scritto senza pensare molto alle prestazioni (più che in altre lingue). E il codice Haskell ottimizzato a mano è spesso piuttosto brutto (anche se suppongo che sia vero anche nella maggior parte delle altre lingue).


1
Puramente funzionale è in realtà una caratteristica di vendita, non un aspetto negativo. Un linguaggio "pigro" non ha senso, pigro vs rigoroso è una questione di tipi, e sia i tipi pigri che quelli rigidi hanno i loro usi. (Quindi Haskell è paralizzato dal non avere tipi rigorosi come la maggior parte delle lingue è paralizzato dal non avere tipi pigri.) I principali aspetti negativi di Haskell sono il suo sistema di moduli schifoso (i moduli non sono di prima classe) e le classi di tipi di fatto effettivamente rompono la modularità (il La regola "un'istanza per tipo" impone al compilatore di mantenere un elenco globale di istanze di classe di tipo).
pyon,

21
"E il codice Haskell ottimizzato a mano è spesso piuttosto brutto (anche se suppongo che sia vero anche nella maggior parte delle altre lingue)." Questo. Quando le persone vogliono mostrare l'eleganza di Haskell, pubblicano codice breve e dolce, che purtroppo ti darebbe prestazioni piuttosto cattive se eseguito su una quantità di dati simile alla produzione. Quando la gente vuole dimostrare che "Haskell è veloce come C ++", pubblicano codice contorto e difficile da leggere, che è ancora più lento di una versione molto più leggibile in C.
quant_dev

12

Non sono un esperto di Haskell: ho imparato le basi ma sfortunatamente non ho avuto la possibilità di fare qualche progetto serio in Haskell (mi piacerebbe, però, perché mi piace molto questa lingua).

Tuttavia, da quello che conosco e da una discussione con qualcuno che ha lavorato in un campo abbastanza vicino alla programmazione funzionale, Haskell potrebbe non essere la soluzione migliore quando si desidera implementare algoritmi di grafici, dove è necessario ad esempio camminare attraverso il grafico ed esibirsi molte modifiche locali sulla struttura del grafico.

Poiché un grafico non ha una struttura ricorsiva in generale, la mia sensazione è che l'approccio migliore sia quello di costruire una copia del grafico usando strutture e puntatori tra loro (come è possibile fare ad esempio in C ++) e manipolare quella copia cambiando puntatori, creando o distruggendo nodi e così via.

Mi chiedo come tali strutture e operazioni di dati possano essere gestite correttamente in Haskell, poiché per quanto ne so in Haskell non è possibile utilizzare la rappresentazione / approccio di cui sopra. Alcuni problemi con gli algoritmi grafici in Haskell sono discussi brevemente in questo articolo

MODIFICARE

Di recente ho parlato con un esperto di programmazione funzionale e ha confermato che implementare in modo efficiente un certo algoritmo grafico può essere piuttosto complicato in Haskell: spostarsi sui puntatori come si fa in C o C ++ può essere molto più veloce.


Note interessanti (e link) sulla manipolazione / attraversamento di grafici in un mondo funzionale puro. Non l'avevo considerato.
Demian Brecht,

7
Gli algoritmi grafici puramente funzionali sono un argomento interessante. La soluzione idiomatica è emulare la rappresentazione imperativa sostituendo i puntatori con dizionari puramente funzionali, ad esempio mappando un dato vertice all'insieme di vertici a cui ha bordi. Tuttavia, a meno che non venga utilizzato un dizionario debole, questo perderà memoria perché non è possibile raccogliere sottografi non raggiungibili e non esiste un dizionario debole puramente funzionale. Alla fine, una soluzione puramente funzionale all'avanguardia è sia molto più complicata che molto meno efficiente!
Jon Harrop,

1
D'altra parte, gli algoritmi grafici possono essere notoriamente difficili da eseguire il debug e la struttura dei dati persistente può alleviare questo problema ...
Jon Harrop,

Mi chiedevo se sarebbe stato possibile sviluppare un tipo di dati del grafico (seguendo l'idea di ByteString: efficiente rappresentazione interna più funzioni di conversione / accesso). Usando le monadi dovrebbe essere possibile rendere mutabili tali grafici. Naturalmente questo affronterebbe il problema di rappresentare i grafici ma non quello di implementare algoritmi di grafi.
Giorgio,

I DAG sono una cosa. Per tutto il resto, puoi sfruttare la pigrizia e "allacciare il nodo".
danielm,

4

Il lato negativo di Haskell è che è diverso. È un passo più lontano dalle lingue più comunemente insegnate o di cui si parla, quindi ci sarà una curva di apprendimento più ampia. È anche meno popolare di una lingua che potrebbe limitare la disponibilità di aiuto se rimani bloccato. Questi in realtà non sono però grandi svantaggi.

L'unica cosa che è un potenziale svantaggio è che è un linguaggio funzionale, quindi è meno utile per alcuni domini problematici, ma questo vale anche per i linguaggi orientati agli oggetti. Generalmente le lingue non hanno veri negativi oltre le curve di apprendimento, almeno per le lingue relativamente popolari. Finché una lingua è Turing completa, è teoricamente capace di tutto.


3
La completezza di Turing è un'aringa rossa. Teoria del calcolo! = Programmazione pratica.

1
@delnan è per questo che ho detto teoricamente
Ryathal il

2
Quali sono quei "domini problematici" per i quali Haskell è presumibilmente meno utile?
Andres F.

3
Mentre è vero che la comunità è più piccola , è effettivamente sproporzionatamente attiva. Penso che il canale #haskell su freenode sia dietro a #python in popolarità all'interno dei canali linguistici, e rispondere alle domande su Haskell su SO è sorprendentemente competitivo :)
Tikhon Jelvis,

@AndresF. - Non andrei fino al punto di dire "meno utile", ma qui ci sono alcune aree in cui Haskell sta ancora mostrando la sua infanzia: 1) DP pesante - Ho codificato un semplice algoritmo a zaino, e sono rimasto letteralmente scioccato da come era lento. Stava usando array inscatolati, quindi mi aspettavo un certo sovraccarico, ma era molto peggio di quanto mi aspettassi. 2) grandi giochi non banali: AFRP è agli inizi, quindi non ci sono framework particolarmente buoni e le prestazioni sono ancora troppo difficili da prevedere. Ci vorrà molto tempo prima di vedere la versione Haskell di Doom. (Frag non conta - non ha AI.)
Persona

0

Quindi, dato questo, quello che sto cercando sono gli svantaggi o i problemi che si presentano con Haskell

I "problemi con Haskell" tendono ad apparire in alcuni domini. Haskell è un linguaggio meraviglioso per la programmazione di applicazioni, molto più piacevole da scrivere di qualsiasi altra cosa. I problemi tendono a insorgere quando si tenta di fare qualcosa per cui non c'è un buon supporto, come ad esempio:

  • Compilazione incrociata. GHC può essere creato come un compilatore incrociato, ma il processo è piuttosto coinvolto.
  • Applicazioni integrate. Haskell ha la gestione della memoria tramite un garbage collector, quindi questo non è troppo sorprendente.
  • Velocità. Haskell non è veloce come Rust, anche se nella maggior parte dei casi competerà abbastanza bene. Dipende molto dal dominio dell'applicazione: i calcoli puri vengono ottimizzati bene, ma qualcosa come "leggere un file in un buffer e contare il numero di righe" è più difficile da esprimere in Haskell.
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.