Ecco un modo per pensarci. Considerare:
answer = 42
magic = 3
specialName :: Int -> String
specialName answer = "the answer to the ultimate question"
specialName magic = "the magic number"
specialName x = "just plain ol' " ++ show x
Riesci a capire perché questo non funzionerà? answer
nella corrispondenza del modello è una variabile, distinta da answer
nell'ambito esterno. Così, invece, dovreste scrivere questo come:
answer = 42
magic = 3
specialName :: Int -> String
specialName x | x == answer = "the answer to the ultimate question"
specialName x | x == magic = "the magic number"
specialName x = "just plain ol' " ++ show x
In realtà, questo è proprio quello che sta succedendo quando si scrive le costanti in un modello. Cioè:
digitName :: Bool -> String
digitName 0 = "zero"
digitName 1 = "one"
digitName _ = "math is hard"
viene convertito dal compilatore per qualcosa di equivalente a:
digitName :: Bool -> String
digitName x | x == 0 = "zero"
digitName x | x == 1 = "one"
digitName _ = "math is hard"
Dal momento che si vuole abbinare contro la funzione legata alla (+)
piuttosto che legano qualsiasi cosa al simbolo (+)
, è' d necessario scrivere il codice come:
instance Show (t -> t-> t) where
show f | f == (+) = "plus"
show f | f == (-) = "minus"
Ma, ciò richiederebbe che le funzioni erano paragonabili per eq ualità. E questo è un problema indecidibile in generale.
Si potrebbe obiettare che si sta solo chiedendo al sistema runtime di confrontare i puntatori di funzione, ma a livello di lingua, il programmatore Haskell non ha accesso ai puntatori. In altre parole, non è possibile modificare i riferimenti ai valori in Haskell (*), solo i valori stessi. Questa è la purezza di Haskell e ottiene trasparenza referenziale.
(*) MVar
s e altri oggetti simili nella monade IO
sono un'altra questione, ma la loro esistenza non invalida il punto.
È fantastico, grazie. (E molto più elegante della soluzione che ho fornito qui sotto.) –
@Sean D: Fa anche una bella illustrazione di dove il tuo mega hack fallire - considera cosa accadrebbe se fosse usato con un operatore sui valori di 'Expression Integer' . 'Sum 6 2' non è uguale a' Literal 8', nonostante il mio codice sia un'istanza perfettamente ragionevole di 'Num'. –