2013-04-05 47 views
5

Sto cercando di capire e comprendere il design di Haskell. Sono attualmente in funzione Lambda/Anonimo e mi stavo chiedendo.Lambda/comprensione concettuale della funzione anonima

Perché le istanze dei tipi di funzione della classe Eq non sono?

Prelude> (\z -> z+5) == (+5) 

In questa domanda, mi chiedevo se è perché z può essere qualsiasi cosa e può essere ancora essere una variabile libera, in tutte le funzioni lambda, quindi sarebbe un difetto di progettazione per rendere le funzioni lambda di tipo Eq .

Perché le istanze dei tipi di funzione della classe di tipo Mostra?

Prelude> (\q -> q-2) 

Apprezzo qualsiasi chiarimento.

Molte grazie in anticipo!

+6

Hai provato a implementarne uno? – is7s

+0

Sì, ho. Capisco come funzionano. Ma questo non mi aiuta veramente a capire il design del linguaggio e perché è stato fatto per non essere esempi di Eq o di tipo classe Show. – AnchovyLegend

+0

Il fatto che devi chiedere già mostra che un'istanza di 'Eq' per le funzioni sarebbe confusa a causa della semantica non chiara. Quando sono uguali le due funzioni? Cosa significherebbe? –

risposta

8

Sono queste funzioni lo stesso o sono differenti:

dbl1 :: Int -> Int 
dbl1 x = x + x 

dbl2 :: Int -> Int 
dlb2 x = 2 * x 

?

Per alcune funzioni è "facile" per il compilatore vedere che contengono la stessa logica. Ma la maggior parte delle funzioni sarebbe estremamente difficile da confrontare. Poi ci sono funzioni che sono logicamente diverse, ma si comportano allo stesso modo - come dbl1 e dbl2 sopra. Quindi, dovresti fare una scelta per testarli contro ogni possibile valore, o decidere che non sono uguali. Il primo è completamente poco pratico nella maggior parte dei casi. Quest'ultimo non è sicuramente desiderabile o intuitivo. Ora, considera che il problema è già troppo difficile da risolvere, quindi getta IO ...

+0

Questo esempio è ancora migliore se aggiungiamo 'dbl1 ', dbl2' :: Double -> Double', con le stesse definizioni ... –

4

Gödel's incompleteness theorems implica che qualsiasi istanza Eq per le funzioni deve fornire risultati inaccurati o talvolta restituire ⊥. Questo non è quello che ci aspettiamo dalle istanze Eq (almeno per i dati limitati).

show deve fornire il codice sorgente Haskell che valuta il suo input. Questo è scomodo quando si compila un programma Haskell, perché ora è necessario conservare una copia del codice sorgente per ogni funzione, gonfiando l'eseguibile, anche se l'istanza Show per le funzioni non viene mai utilizzata.

È possibile fornire un'istanza Show per le funzioni che infrange questa regola, ad es. restituendo sempre "{-function-}" o (per alcuni tipi) restituendo il tipo di funzione. Le prime versioni di Haskell lo fecero. Ma si è ritenuto che rompere questa regola non fosse una buona idea.

+4

Non sono d'accordo con entrambe queste risposte. Il primo perché è molto comune avere istanze di 'Eq' per dati infiniti che funzionano esattamente come si descrivono, e dal momento che possiamo rappresentare molte funzioni semplicemente come mappature infinite di input -> output il problema è in effetti lo stesso. Trascinando Godel in questo sembra piuttosto inverosimile (e anche il trascinamento nel problema dell'arresto è oltre il punto). Il tuo secondo punto sembra altrettanto sciocco. – sclv

+1

Il vero problema in entrambi i casi è l'uguaglianza intensionale rispetto all'estensione (o immagino sintattico vs semantico). La semantica di Haskell detta il secondo, ma tutto ciò che possiamo catturare per la tua proposta 'Show' è il primo. "Eq", d'altra parte, è possibile su domini finiti, ma questo è un sottogruppo ristretto di ciò che potremmo volere e inefficiente da avviare. – sclv

+4

No, @sclv, il teorema di incompletezza di Godel è pertinente. Si consideri una funzione che restituisce tutti i numeri pari e un'altra che restituisce i numeri pari che sono la somma di due numeri primi più piccoli. Sono uguali? Sono impressionato se puoi scrivere un programma Haskell in grado di risolvere un problema irrisolto dai matematici per secoli, e che non sappiamo sia risolvibile. Godel mostra che ci sono verità non provabili in qualsiasi sistema matematico abbastanza sofisticato da includere l'aritmetica - quindi qualsiasi istanza di Eq per le funzioni deve essere errata o incompleta e incompleta nel senso di non terminare. – AndrewC

6

Un concetto critico che ritengo né Dave né Peter abbiano sottolineato abbastanza: due funzioni sono uguali se e solo se (a) hanno lo stesso tipo, e (b) per ogni possibile argomento che puoi dare loro, entrambi producono lo stesso risultato.

Ora, con questo chiaro, la risposta per Eq è proprio quello che hanno detto. Peter sottolinea che un'istanza Eq per le funzioni dovrebbe essere in grado di analizzare due funzioni arbitrarie e determinare correttamente se producono lo stesso risultato per due input. E come sottolinea Dave, questo è in realtà matematicamente impossibile; qualsiasi correttore che ha provato a confrontare funzioni arbitrarie fallirà per alcune funzioni, il che significa che si bloccherà o produrrà una risposta errata per alcuni casi.

vedrete programmatori Haskell parlare di parità di funzioni per tutto il tempo, però, ma la maggior parte del tempo il loro significato è che gli esseri umani hanno dimostrato che alcune due funzioni sono uguali. Ad esempio, l'operatore composizione funzione è definita in questo modo:

(.) :: (b -> c) -> (a -> b) -> (a -> c) 
f . g = \x -> f (g x) 

Possiamo ora dimostrare che per ogni possibile h :: c -> d, g :: b -> c e h :: a -> b, f . (g . h) == (f . g) . h. E 'abbastanza facile in questo caso, abbiamo semplicemente ampliare l'espressioni secondo la definizione di (.), e noi ottenere la stessa cosa per entrambi:

f . (g . h) = f . (\y -> g (h y))   -- expand `g . h` by definition 
      = \x -> f ((\y -> g (h y)) x) -- expand `f . (\y -> g (h y))` 
      = \x -> f (g (h x))   -- apply the inner lambda 

(f . g) . h = (\y -> f (g y)) . h 
      = \x -> (\y -> f (g y)) (h x) 
      = \x -> f (g (h x)) 

Ma questo può essere fatto solo per le funzioni scelti con cura, e computer in genere può Fallo bene o in modo affidabile. Per ogni programma che scrivi per provare e testare l'uguaglianza delle funzioni arbitrarie, ci saranno alcune funzioni per le quali produrranno la risposta sbagliata o il ciclo per sempre.

+4

i computer possono mostrare che le funzioni sono uguali anche - il punto è che non è * decidibile * (in generale), e questo vale sia per gli umani che per le macchine. Non riesco a risolvere il problema dell'arresto in generale, vero? –

+0

Vero. Stavo cercando di semplificare, ma sì, è un ponte troppo lontano. Lo modifico –

+0

Non direi che ci sono funzioni che non possono essere confrontate per l'uguaglianza. Qualunque possibile controllo di uguaglianza di funzioni ha casi che lo sconfiggeranno, ma non sono gli stessi casi per ogni correttore. – Ben

1

Mi piacciono le risposte di tutti ... sembrano avere un senso. Non immaginerei, in questa fase, di rispondere perché le funzioni non sono impostate di default come istanze di Eq e Show. Questa è solo una sperimentazione che potrebbe darti delle idee per provarlo tu stesso:

Prelude> :set -XFlexibleInstances 
Prelude> instance Eq (Int -> Int) where x == y = map x [0..10] == map y [0..10] 
Prelude> ((\z -> z+5) :: Int -> Int) == ((+5) :: Int -> Int) 
True 
Prelude> instance Show (Int -> Int) where show x = show (zip [0..10] (map x [0..10])) 
Prelude> (\q -> q-2) :: (Int -> Int) 
[(0,-2),(1,-1),(2,0),(3,1),(4,2),(5,3),(6,4),(7,5),(8,6),(9,7),(10,8)] 
Problemi correlati