2016-03-02 10 views
7

Quando si cerca di imparare Haskell, una delle difficoltà che si presentano è l'abilità quando qualcosa richiede una magia speciale dal compilatore. Un esempio che viene in mente è la funzione seq che non può essere definita, ad esempio non è possibile creare una funzione seq2 che si comporti esattamente come seq integrata. Di conseguenza, quando si insegna a qualcuno su seq, è necessario ricordare che lo seq è speciale perché è un simbolo speciale per il compilatore.Magia del compilatore Haskell: cosa richiede un trattamento speciale dal compilatore?

Un altro esempio potrebbe essere la do -notazione che funziona solo con le istanze della classe Monad.

A volte, non è sempre ovvio. Ad esempio, continuazioni. Il compilatore sa di Control.Monad.Cont o è semplicemente la vecchia Haskell che avresti potuto inventarti? In questo caso, penso che dal compilatore non sia richiesto nulla di speciale, anche se le continuazioni sono un tipo di bestia molto strano.

Le estensioni di lingua mettono da parte, di quali altri compilatori di magia dovrebbero essere a conoscenza gli studenti di Haskell?

+1

Dichiarare l'ovvio: qualsiasi cosa 'IO' ricada sotto" magia "per qualsiasi ragionevole definizione di" magia ": https://www.reddit.com/r/haskell/comments/450baq/is_it_just_me_or_does_ios_definition_give_you_the/. Anche la monade 'ST', che probabilmente è ancora più magica. – PyRulez

+1

Che mi dici di STM? E fusione di corrente? – gawi

+0

sì anche quelli, ma STM ottiene la sua magia da IO, e la fusione di vapore è regole di riscrittura, che è di per sé magica. – PyRulez

risposta

5

Quasi tutti i primitivi ghc che non possono essere implementati in userland sono nel pacchetto ghc-prim. (c'è anche un modulo chiamato GHC.Magic lì!)

Quindi la navigazione darà un senso.

Nota che è necessario non utilizzare questo modulo in codice userland a meno che non si sappia esattamente cosa si sta facendo. La maggior parte delle risorse utilizzabili vengono esportate nei moduli downstream in base, a volte in forma modificata. Quelle sedi downstream e API sono considerate più stabili, mentre ghc-prim non fornisce garanzie su come agirà da una versione all'altra. roba

Il GHC-specifico è riesportato in GHC.Exts, ma un sacco di altre cose andare in Prelude (come ad esempio i tipi di base di dati, così come seq) o le librerie di concorrenza, ecc

1

polimorfico seq è sicuramente Magia. È possibile implementare seq per qualsiasi specifica tipo, ma solo il compilatore possibile implementare una funzione per tutti i possibili tipi [ed evitare l'ottimizzazione via anche se sembra no-op].

Ovviamente l'intero IO Monade è profondamente magia, come è tutto con concorrenza e parallelismo (par, forkIO, MVar), stoccaggio mutevole, eccezione lancio e la cattura, interrogando il garbage collector e run-time previsti, ecc

Il monad IO può essere considerato un caso speciale della monade ST, che è anche magico. (Permette lo storage veramente mutevole, che richiede materiale di basso livello.)

Il monad State, d'altra parte, è un codice a livello utente completamente comune che chiunque può scrivere. Così è la monade Cont. Così sono le varie monadi di eccezione/errore.

Tutto ciò che ha a che fare con la sintassi (blocchi di istruzioni, list comprehensions) è cablato nella definizione della lingua.(Si noti, tuttavia, che alcuni di questi rispondono a LANGUAGE RebindableSyntax, che consente di modificare le funzioni a cui si lega.) Anche le cose deriving; il compilatore "conosce" una manciata di classi speciali e come generare automaticamente istanze per loro. Derivante per newtype funziona per qualsiasi classe. (Si tratta semplicemente di copiare un'istanza da un tipo a un'altra copia identica di quel tipo.)

Gli array sono cablati. Proprio come ogni altro linguaggio di programmazione.

Tutta l'interfaccia di funzione esterna è chiaramente cablata.

STM può può essere implementato nel codice utente (l'ho fatto), ma attualmente è cablato. (Immagino che questo dia un significativo vantaggio in termini di prestazioni. Non ho provato a misurarlo effettivamente.) Ma concettualmente, questa è solo un'ottimizzazione; Il è in grado di implementarlo utilizzando le primitive di concorrenza esistenti di livello inferiore,.