Qual è il problema di Haskell? [chiuso]


109

Conosco alcuni programmatori che continuano a parlare di Haskell quando sono tra di loro, e qui su SO tutti sembrano amare quel linguaggio. Essere bravo in Haskell sembra un po 'come il segno distintivo di un geniale programmatore.

Qualcuno può fornire alcuni esempi Haskell che mostrano perché è così elegante / superiore?

Risposte:


134

Il modo in cui mi è stato proposto, e quello che penso sia vero dopo aver lavorato sull'apprendimento su Haskell per un mese ormai, è il fatto che la programmazione funzionale distorce il tuo cervello in modi interessanti: ti costringe a pensare a problemi familiari in modi diversi : invece di loop, pensa in mappe, pieghe e filtri, ecc. In generale, se hai più di una prospettiva su un problema, ti rende più abilitato a ragionare su questo problema e cambia i punti di vista se necessario.

L'altra cosa veramente interessante di Haskell è il suo sistema di tipi. È strettamente digitato, ma il motore di inferenza del tipo lo fa sembrare un programma Python che ti dice magicamente quando hai fatto uno stupido errore relativo al tipo. I messaggi di errore di Haskell a questo proposito sono in qualche modo carenti, ma man mano che acquisirai maggiore familiarità con la lingua ti dirai: questo è ciò che dovrebbe essere la digitazione!


47
Va notato che i messaggi di errore di Haskell non mancano, quelli di ghc sì. Lo standard Haskell non specifica come vengono eseguiti i messaggi di errore.
PyRulez

Per la plebe come me, GHC sta per Glasgow Haskell Compiler. en.wikipedia.org/wiki/Glasgow_Haskell_Compiler
Lorem Ipsum

137

Questo è l' esempio che mi ha convinto a imparare Haskell (e ragazzo sono contento di averlo fatto).

-- program to copy a file --
import System.Environment

main = do
         --read command-line arguments
         [file1, file2] <- getArgs

         --copy file contents
         str <- readFile file1
         writeFile file2 str

OK, è un programma breve e leggibile. In questo senso è meglio di un programma C. Ma come è così diverso da (diciamo) un programma Python con una struttura molto simile?

La risposta è una valutazione pigra. Nella maggior parte dei linguaggi (anche alcuni funzionali), un programma strutturato come quello sopra comporterebbe il caricamento dell'intero file in memoria, e quindi la riscrittura con un nuovo nome.

Haskell è "pigro". Non calcola le cose finché non ne ha bisogno, e per estensione non calcola le cose di cui non ha mai bisogno. Ad esempio, se dovessi rimuovere il filewriteFile riga, Haskell non si preoccuperebbe di leggere nulla dal file in primo luogo.

Così com'è, Haskell si rende conto che writeFiledipende dareadFile , e quindi è in grado di ottimizzare questo percorso dati.

Mentre i risultati dipendono dal compilatore, ciò che accade tipicamente quando esegui il programma sopra è questo: il programma legge un blocco (diciamo 8KB) del primo file, quindi lo scrive nel secondo file, quindi legge un altro blocco dal primo file e lo scrive nel secondo file e così via. (Prova a correrestrace sopra!)

... che assomiglia molto a ciò che farebbe l'implementazione efficiente in C di una copia di file.

Quindi, Haskell ti consente di scrivere programmi compatti e leggibili, spesso senza sacrificare molte prestazioni.

Un'altra cosa che devo aggiungere è che Haskell rende semplicemente difficile scrivere programmi difettosi. Lo straordinario sistema di tipi, la mancanza di effetti collaterali e, naturalmente, la compattezza del codice Haskell riducono i bug per almeno tre motivi:

  1. Migliore progettazione del programma. La complessità ridotta porta a meno errori logici.

  2. Codice compatto. Meno righe per la presenza di bug.

  3. Errori di compilazione. Molti bug non sono validi Haskell .

Haskell non è per tutti. Ma tutti dovrebbero provarlo.


Come cambieresti esattamente la costante di 8KB (o qualunque cosa sia)? Perché scommetterei che un'implementazione Haskell sarebbe altrimenti più lenta di una versione C, specialmente senza prefetching ...
user541686

1
@Mehrdad Puoi modificare la dimensione del buffer con hSetBuffering handle (BlockBuffering (Just bufferSize)).
David

3
È sorprendente che questa risposta abbia 116 voti positivi, ma quello che c'è dentro è semplicemente sbagliato. Questo programma sarà leggere l'intero file, a meno che non si utilizza stringhe di byte pigri (che si può fare con Data.Bytestring.Lazy.readFile), che non hanno nulla a che fare con Haskell di essere un pigro (non-strict) lingua. Le monadi stanno sequenziando - questo significa che all'incirca "tutti gli effetti collaterali vengono eliminati quando si elimina il risultato". Per quanto riguarda la magia "pigro Bytestring": questo è pericoloso, e puoi farlo con una sintassi simile o più semplice nella maggior parte degli altri linguaggi.
Jo So

14
Il vecchio standard noioso fa readFileanche l'IO pigro allo stesso modo Data.ByteString.Lazy.readFile. Quindi la risposta non è sbagliata e non è semplicemente un'ottimizzazione del compilatore. In effetti, questo fa parte delle specifiche per Haskell : "La readFilefunzione legge un file e restituisce il contenuto del file come una stringa. Il file viene letto pigramente, su richiesta, come con getContents."
Daniel Wagner

1
Penso che le altre risposte puntino a cose che sono più speciali di Haskell. Molte lingue / ambienti hanno corsi d'acqua, si può fare qualcosa di simile in Node: const fs = require('fs'); const [file1, file2] = process.argv.slice(2); fs.createReadStream(file1).pipe(fs.createWriteStream(file2)). Anche Bash ha qualcosa di simile:cat $1 > $2
Max Heiber

64

Stai facendo la domanda sbagliata.

Haskell non è una lingua in cui vai a guardare alcuni esempi interessanti e dici "aha, ora capisco, ecco ciò che lo rende buono!"

È più come se abbiamo tutti questi altri linguaggi di programmazione, e sono tutti più o meno simili, e poi c'è Haskell che è totalmente diverso e stravagante in un modo che è assolutamente fantastico una volta che ci si abitua alla stravaganza. Ma il problema è che ci vuole un po 'per abituarsi alla stravaganza. Cose che distinguono Haskell da quasi tutti gli altri linguaggi anche semi-mainstream:

  • Valutazione pigra
  • Nessun effetto collaterale (tutto è puro, IO / ecc. Avviene tramite monadi)
  • Sistema di tipi statici incredibilmente espressivo

così come alcuni altri aspetti che sono diversi da molte lingue tradizionali (ma condivisi da alcuni):

  • funzionale
  • spazi bianchi significativi
  • tipo dedotto

Come hanno risposto altri poster, la combinazione di tutte queste caratteristiche significa che pensi alla programmazione in un modo completamente diverso. E quindi è difficile trovare un esempio (o una serie di esempi) che lo comunichi adeguatamente al programmatore Joe-mainstream. È una cosa esperienziale. (Per fare un'analogia, posso mostrarti le foto del mio viaggio in Cina del 1970, ma dopo aver visto le foto, non saprai ancora com'era aver vissuto lì in quel periodo. Allo stesso modo, posso mostrarti un Haskell 'quicksort', ma ancora non saprai cosa significa essere un Haskeller.)


17
Non sono d'accordo con la tua prima frase. Inizialmente sono rimasto davvero colpito da alcuni esempi di codice Haskell e ciò che mi ha davvero convinto che valesse la pena di imparare è stato questo articolo: cs.dartmouth.edu/~doug/powser.html Ma ovviamente questo è interessante per un matematico / fisico. Un programmatore che esamina le cose del mondo reale troverebbe questo esempio ridicolo.
Rafael S. Calsaverini

2
@Rafael: Questo solleva la domanda "da cosa sarebbe impressionato un programmatore che esamina le cose del mondo reale"?
JD

Buona domanda! Non sono un programmatore del "mondo reale" quindi non so cosa gli piace. hahaha ... so cosa piace a fisici e matematici. : P
Rafael S. Calsaverini

27

Ciò che distingue davvero Haskell è lo sforzo che compie nel suo design per applicare la programmazione funzionale. Puoi programmare in uno stile funzionale praticamente in qualsiasi lingua, ma è fin troppo facile abbandonare alla prima comodità. Haskell non ti permette di abbandonare la programmazione funzionale, quindi devi portarla alla sua conclusione logica, che è un programma finale su cui è più facile ragionare, ed elude un'intera classe dei tipi più spinosi di bug.

Quando si tratta di scrivere un programma per il mondo reale, potresti scoprire che Haskell manca in qualche modo pratico, ma la tua soluzione finale sarà migliore per aver conosciuto Haskell per cominciare. Sicuramente non sono ancora arrivato, ma finora imparare Haskell è stato molto più illuminante di quanto si possa dire, Lisp era al college.


1
Bene, c'è sempre la possibilità di usare sempre e solo la monade ST e / o unsafePerformIOper le persone che vogliono solo vedere il mondo bruciare;)
sara

22

Parte del problema è che la purezza e la tipizzazione statica consentono il parallelismo combinato con ottimizzazioni aggressive. Le lingue parallele sono calde ora con il multicore che è un po 'dirompente.

Haskell offre più opzioni per il parallelismo rispetto a praticamente qualsiasi linguaggio generico, insieme a un veloce compilatore di codice nativo. Non c'è davvero concorrenza con questo tipo di supporto per stili paralleli:

Quindi, se ti interessa far funzionare il tuo multicore, Haskell ha qualcosa da dire. Un ottimo punto di partenza è il tutorial di Simon Peyton Jones sulla programmazione parallela e concorrente in Haskell .


"insieme a un veloce compilatore di codice nativo"?
JD

Credo che dons si riferisca a GHCI.
Gregory Higley

3
@ Jon: shootout.alioth.debian.org/u32/… Haskell se la cava abbastanza bene nella sparatoria, per esempio.
Peaker

4
@ Jon: Il codice della sparatoria è molto vecchio e proviene da un lontano passato in cui GHC era meno un compilatore ottimizzante. Tuttavia, dimostra che il codice Haskell può andare a basso livello per ottenere prestazioni, se necessario. Le soluzioni più recenti nella sparatoria sono più idiomatiche e comunque veloci.
Peaker

1
@GregoryHigley C'è una differenza tra GHCI e GHC.
Jeremy List

18

La memoria transazionale software è un modo piuttosto interessante per gestire la concorrenza. È molto più flessibile del passaggio di messaggi e non soggetto a deadlock come i mutex. L' implementazione di STM da parte di GHC è considerata una delle migliori.


18

Ho passato l'ultimo anno imparando Haskell e scrivendovi un progetto ragionevolmente ampio e complesso. (Il progetto è un sistema automatizzato di trading di opzioni e tutto, dagli algoritmi di trading all'analisi e alla gestione di feed di dati di mercato di basso livello e ad alta velocità, è fatto in Haskell.) È considerevolmente più conciso e più facile da capire (per quelli con sfondo appropriato) rispetto a una versione Java, oltre che estremamente robusta.

Forse la vittoria più grande per me è stata la capacità di modulare il flusso di controllo attraverso cose come monoidi, monadi e così via. Un esempio molto semplice sarebbe l'Ordering monoid; in un'espressione come

c1 `mappend` c2 `mappend` c3

dove c1e così via di ritorno LT, EQo GT, c1restituendo EQcause l'espressione di continuare, valutando c2; se c2restituisce LTo GTquesto è il valore dell'intero, ec3 non viene valutato. Questo genere di cose diventa considerevolmente più sofisticato e complesso in cose come generatori di messaggi monadici e parser in cui potrei portare in giro diversi tipi di stato, avere condizioni di interruzione variabili, o potrei voler essere in grado di decidere per qualsiasi chiamata particolare se abortire davvero significa "nessuna ulteriore elaborazione" o significa "restituire un errore alla fine, ma continuare l'elaborazione per raccogliere ulteriori messaggi di errore".

Questa è tutta roba che richiede un po 'di tempo e probabilmente un certo sforzo per imparare, e quindi può essere difficile argomentare in modo convincente per coloro che non conoscono già queste tecniche. Penso che All About Monads tutorial dia una dimostrazione piuttosto impressionante di un aspetto di questo, ma non mi aspetto che qualcuno che non abbia già familiarità con il materiale lo "capisca" alla prima, o anche alla terza, attenta lettura.

Ad ogni modo, ci sono anche molte altre cose buone in Haskell, ma questa è una delle principali che non vedo menzionata così spesso, probabilmente perché è piuttosto complessa.


2
Molto interessante! Quante righe di codice Haskell sono state inserite in totale nel tuo sistema di trading automatizzato? Come hai gestito la tolleranza ai guasti e quali tipi di risultati di prestazioni hai ottenuto? Recentemente ho pensato che Haskell ha il potenziale per essere buono per la programmazione a bassa latenza ...
JD

12

Per un esempio interessante puoi guardare: http://en.literateprograms.org/Quicksort_(Haskell)

Ciò che è interessante è esaminare l'implementazione in varie lingue.

Ciò che rende Haskell così interessante, insieme ad altri linguaggi funzionali, è il fatto che devi pensare in modo diverso a come programmare. Ad esempio, generalmente non utilizzerai i cicli for o while, ma utilizzerai la ricorsione.

Come accennato in precedenza, Haskell e altri linguaggi funzionali eccellono con l'elaborazione parallela e le applicazioni di scrittura per lavorare su multi-core.


2
la ricorsione è la bomba. quello e il pattern matching.
Ellery Newcomer

1
Liberarmi dei cicli for e while è la parte più difficile per me quando scrivo in un linguaggio funzionale. :)
James Black

4
Imparare a pensare in modo ricorsivo invece che in loop è stata la parte più difficile anche per me. Quando finalmente è entrato in scena, è stata una delle più grandi epifanie di programmazione che abbia mai avuto.
Chris Connett,

8
Tranne che il programmatore Haskell funzionante usa raramente la ricorsione primitiva; principalmente usi funzioni di libreria come map e foldr.
Paul Johnson,

18
Trovo più interessante il fatto che l'algoritmo originale di Quicksort di Hoare sia stato imbastardito in questa forma fuori luogo basata su elenchi apparentemente in modo che le implementazioni inutilmente inefficienti potessero essere scritte "elegantemente" in Haskell. Se provi a scrivere un vero quicksort (sul posto) in Haskell, scoprirai che è brutto da morire. Se provi a scrivere un quicksort generico competitivo in Haskell, scoprirai che è effettivamente impossibile a causa di bug di vecchia data nel garbage collector di GHC. Salutando il quicksort come un buon esempio per la credenza dei mendicanti Haskell, IMHO.
JD

8

Non potrei farti un esempio, sono un ragazzo di OCaml, ma quando sono in una situazione come te, la curiosità prende piede e devo scaricare un compilatore / interprete e provarlo. Probabilmente imparerai molto di più in questo modo sui punti di forza e di debolezza di un dato linguaggio funzionale.


1
Non dimenticare di leggere il codice sorgente del compilatore. Questo ti darà anche molte informazioni preziose.
JD

7

Una cosa che trovo molto interessante quando si tratta di algoritmi o problemi matematici è la valutazione pigra intrinseca di Haskell dei calcoli, che è possibile solo a causa della sua natura funzionale rigorosa.

Ad esempio, se vuoi calcolare tutti i numeri primi, puoi usare

primes = sieve [2..]
    where sieve (p:xs) = p : sieve [x | x<-xs, x `mod` p /= 0]

e il risultato è in realtà un elenco infinito. Ma Haskell lo valuterà da sinistra a destra, quindi finché non provi a fare qualcosa che richiede l'intero elenco, puoi comunque usarlo senza che il programma si blocchi all'infinito, come ad esempio:

foo = sum $ takeWhile (<100) primes

che somma tutti i numeri primi inferiori a 100. Questo è utile per diversi motivi. Prima di tutto, ho solo bisogno di scrivere una funzione prime che generi tutti i numeri primi e poi sono praticamente pronto a lavorare con i numeri primi. In un linguaggio di programmazione orientato agli oggetti, avrei bisogno di un modo per dire alla funzione quanti numeri primi deve calcolare prima di restituire, o emulare il comportamento della lista infinita con un oggetto. Un'altra cosa è che in generale, finisci per scrivere codice che esprime ciò che vuoi calcolare e non in quale ordine valutare le cose - invece il compilatore lo fa per te.

Questo non è utile solo per liste infinite, infatti viene utilizzato senza che tu lo sappia tutto il tempo quando non c'è bisogno di valutare più del necessario.


2
Questo non è del tutto vero; con il comportamento yield return di C # (un linguaggio orientato agli oggetti), puoi anche dichiarare elenchi infiniti che vengono valutati su richiesta.
Jeff Yates

2
Buon punto. Hai ragione e dovrei evitare di affermare ciò che può e non può essere fatto in altre lingue in modo così categorico. Penso che il mio esempio fosse imperfetto, ma penso ancora che tu guadagni qualcosa dal modo di Haskell di valutare pigro: è davvero lì per impostazione predefinita e senza alcuno sforzo da parte del programmatore. E questo, credo, sia dovuto alla sua natura funzionale e all'assenza di effetti collaterali.
waxwing

8
Potresti essere interessato a leggere perché "sieve" non è il setaccio di Eratostene: lambda-the-ultimate.org/node/3127
Chris Conway,

@ Chris: Grazie, in realtà è stato un articolo piuttosto interessante! La funzione dei numeri primi di cui sopra non è quella che ho utilizzato per i miei calcoli poiché è dolorosamente lenta. Tuttavia, l'articolo fa emergere un buon punto sul fatto che controllare tutti i numeri per la mod è davvero un algoritmo diverso.
waxwing

6

Sono d'accordo con altri sul fatto che vedere alcuni piccoli esempi non è il modo migliore per mettere in mostra Haskell. Ma ne darò comunque un po '. Ecco una soluzione fulminea ai problemi 18 e 67 del progetto Eulero , che ti chiedono di trovare il percorso della somma massima dalla base all'apice di un triangolo:

bottomUp :: (Ord a, Num a) => [[a]] -> a
bottomUp = head . bu
  where bu [bottom]     = bottom
        bu (row : base) = merge row $ bu base
        merge [] [_] = []
        merge (x:xs) (y1:y2:ys) = x + max y1 y2 : merge xs (y2:ys)

Ecco un'implementazione completa e riutilizzabile dell'algoritmo BubbleSearch di Lesh e Mitzenmacher. L'ho usato per imballare file multimediali di grandi dimensioni per l'archiviazione su DVD senza sprechi:

data BubbleResult i o = BubbleResult { bestResult :: o
                                     , result :: o
                                     , leftoverRandoms :: [Double]
                                     }
bubbleSearch :: (Ord result) =>
                ([a] -> result) ->       -- greedy search algorithm
                Double ->                -- probability
                [a] ->                   -- list of items to be searched
                [Double] ->              -- list of random numbers
                [BubbleResult a result]  -- monotone list of results
bubbleSearch search p startOrder rs = bubble startOrder rs
    where bubble order rs = BubbleResult answer answer rs : walk tries
            where answer = search order
                  tries  = perturbations p order rs
                  walk ((order, rs) : rest) =
                      if result > answer then bubble order rs
                      else BubbleResult answer result rs : walk rest
                    where result = search order

perturbations :: Double -> [a] -> [Double] -> [([a], [Double])]
perturbations p xs rs = xr' : perturbations p xs (snd xr')
    where xr' = perturb xs rs
          perturb :: [a] -> [Double] -> ([a], [Double])
          perturb xs rs = shift_all p [] xs rs

shift_all p new' [] rs = (reverse new', rs)
shift_all p new' old rs = shift_one new' old rs (shift_all p)
  where shift_one :: [a] -> [a] -> [Double] -> ([a]->[a]->[Double]->b) -> b
        shift_one new' xs rs k = shift new' [] xs rs
          where shift new' prev' [x] rs = k (x:new') (reverse prev') rs
                shift new' prev' (x:xs) (r:rs) 
                    | r <= p    = k (x:new') (prev' `revApp` xs) rs
                    | otherwise = shift new' (x:prev') xs rs
                revApp xs ys = foldl (flip (:)) ys xs

Sono sicuro che questo codice sembra senza senso casuale. Ma se leggi il post del blog di Mitzenmacher e comprendi l'algoritmo, rimarrai stupito dal fatto che sia possibile impacchettare l'algoritmo in codice senza dire nulla su ciò che stai cercando.

Dopo averti fornito alcuni esempi come hai chiesto, dirò che il modo migliore per iniziare ad apprezzare Haskell è leggere il documento che mi ha dato le idee di cui avevo bisogno per scrivere il DVD packer: Why Functional Programming Matters di John Hughes. L'articolo in realtà precede Haskell, ma spiega brillantemente alcune delle idee che rendono le persone come Haskell.


5

Per me, l'attrazione di Haskell è la promessa di correttezza garantita dal compilatore . Anche se è per parti pure del codice.

Ho scritto un sacco di codice di simulazione scientifica, e sono domandato così tante volte se ci fosse un bug nei miei codici precedenti, che potrebbe invalidare un sacco di lavoro in corso.


6
Come garantisce la correttezza?
Jonathan Fischoff

Le parti pure del codice sono molto più sicure di quelle impure. Il livello di fiducia / impegno investito è molto più alto.
rpg

1
Cosa ti ha dato questa impressione?
JD

5

Trovo che per alcune attività sono incredibilmente produttivo con Haskell.

Il motivo è dovuto alla sintassi succinta e alla facilità di test.

Ecco come è la sintassi della dichiarazione di funzione:

foo a = a + 5

Questo è il modo più semplice in cui posso pensare di definire una funzione.

Se scrivo l'inverso

inverseFoo a = a - 5

Posso verificare che sia inverso per qualsiasi input casuale scrivendo

prop_IsInverse :: Double -> Bool
prop_IsInverse a = a == (inverseFoo $ foo a)

E chiamando dalla riga di comando

jonny @ ubuntu: runhaskell quickCheck + nomi fooFileName.hs

Che controllerà che tutte le proprietà nel mio file siano mantenute, testando casualmente gli input cento volte.

Non penso che Haskell sia il linguaggio perfetto per tutto, ma quando si tratta di scrivere piccole funzioni e testare, non ho visto niente di meglio. Se la tua programmazione ha una componente matematica, questo è molto importante.


Quali problemi stai risolvendo e quali altre lingue hai provato?
JD

1
Grafica 3D in tempo reale per cellulari e iPad.
Jonathan Fischoff

3

Se riesci a capire il sistema di caratteri in Haskell, penso che di per sé sia ​​un bel risultato.


1
Cosa c'è da ottenere? Se devi, pensa "data" == "class" e "typeclass" = "interfaccia" / "ruolo" / "tratto". Non potrebbe essere più semplice. (Non c'è nemmeno "null" per incasinarti. Null è un concetto che puoi inserire tu stesso nel tuo tipo.)
jrockway

8
C'è molto da ottenere, jrockway. Anche se tu ed io lo troviamo relativamente semplice, molte persone, anche molti sviluppatori, trovano alcuni tipi di astrazioni molto difficili da capire. Conosco molti sviluppatori che ancora non afferrano del tutto l'idea di puntatori e riferimenti in linguaggi più tradizionali, anche se li usano ogni giorno.
Gregory Higley

2

non ha costrutti di ciclo. non molte lingue hanno questa caratteristica.


17
ghci>: m + Control.Monad ghci> forM_ [1..3] print 1 2 3
sastanin

1

Sono d'accordo con coloro che hanno affermato che la programmazione funzionale porta il cervello a vedere la programmazione da un'angolazione diversa. L'ho usato solo come hobbista, ma penso che abbia cambiato radicalmente il modo in cui affronta un problema. Non credo che sarei stato altrettanto efficace con LINQ senza essere stato esposto a Haskell (e utilizzando generatori e comprensioni di elenchi in Python).


-1

Per esprimere una visione contrarian: Steve Yegge scrive che le lingue Hindely-Milner mancano della flessibilità richiesta per scrivere buoni sistemi :

HM è molto carino, in un senso matematico formale totalmente inutile. Gestisce molto bene alcuni costrutti di calcolo; l'invio di corrispondenza del modello trovato in Haskell, SML e OCaml è particolarmente utile. Non sorprende che gestisca goffamente alcuni altri costrutti comuni e altamente desiderabili nella migliore delle ipotesi, ma spiegano quegli scenari dicendo che ti sbagli, in realtà non li vuoi. Sai, cose come, oh, impostare le variabili.

Vale la pena imparare Haskell, ma ha i suoi punti deboli.


5
Mentre è certamente vero che i sistemi di tipo forte generalmente richiedono che tu aderisca a loro (questo è ciò che rende utile la loro forza), è anche vero che molti (la maggior parte?) Sistemi di tipo basati su HM esistenti, in effetti, hanno una sorta di ' escape hatch 'come descritto nel link (prendi Obj.magic in O'Caml come esempio, anche se non l'ho mai usato se non come hack); in pratica, tuttavia, per molti tipi di programmi non è mai necessario un dispositivo del genere.
Zach Snow

3
La questione se l'impostazione delle variabili sia "desiderabile" dipende da quanto dolore è usare i costrutti alternativi rispetto a quanto dolore è causato dall'uso delle variabili. Questo non è per respingere l'intero argomento, ma piuttosto per sottolineare che prendere l'affermazione "le variabili sono un costrutto altamente desiderabile" come assioma non è la base di un argomento convincente. È semplicemente il modo in cui la maggior parte delle persone impara a programmare.
gtd

5
-1: Le dichiarazioni di Steve sono in parte obsolete ma per lo più completamente sbagliate di fatto. La restrizione dei valori rilassata di OCaml e il sistema di tipi di .NET sono alcuni ovvi esempi di contro alle sue dichiarazioni.
JD

4
Steve Yegge ha un ape irragionevole nel suo cofano sulla digitazione statica, e non solo la maggior parte di ciò che dice a riguardo è sbagliato, ma continua anche a tirarlo fuori in ogni occasione disponibile (e anche alcune non disponibili). Faresti bene a fidarti solo della tua esperienza al riguardo.
ShreevatsaR

3
Sebbene non sia d'accordo con Yegge sulla digitazione statica e dinamica, Haskell ha il tipo Data.Dynamic. Se vuoi la digitazione dinamica, puoi averla!
jrockway
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.