2015-02-26 7 views
7

Dopo aver letto l'esempio di RPN calculator in "Learn You a Haskell for Great Good!" Volevo riscriverlo io stesso in un modo più generale.Come scrivere questa espressione caso con la sintassi del modello di vista?

Per estendere facilmente le funzioni disponibili, le ho messe in elenchi e schemi separati abbinati alla funzione lookup utilizzando la sintassi ViewPatterns. Per leggere l'input con read ho scritto questo:

parse xs x = case readMaybe x of 
    Just x -> Right (x : xs) 
    Nothing -> Left "Syntax error 

ma preferirei evitare un'espressione caso e utilizzare di nuovo il modello vista in questo modo:

parse xs (readMaybe -> Just x) = Right (x : xs) 
parse xs (readMaybe -> Nothing) = Left "Syntax error" 

Tuttavia, con questi ultimi che sto ricevendo questo errore: No instance for (Read a0) arising from a use of ‘readMaybe’

Non capisco perché. Non sono equivalenti?

L'intero codice è here.

risposta

11

Non sono equivalenti. La versione case ha uno readMaybe, la versione del modello di visualizzazione ne ha due. Per ogni readMaybe, il compilatore deve inferire quale tipo è la destinazione del tentativo di leggere. Quando il codice dice

parse xs x = case readMaybe x of 
    Just x -> Right (x : xs) 
    Nothing -> Left "Syntax error 

il detective GHC si accorge che nel vostro caso Just x, x finisce Consed a xs, e così deve prendere qualsiasi tipo gli elementi di xs hanno. E questo è un buon lavoro.

Ma quando si scrive

parse xs (readMaybe -> Just x) = Right (x : xs) 
parse xs (readMaybe -> Nothing) = Left "Syntax error" 

si creano due problemi find-the-bersaglio-tipo separati, uno per ogni utilizzo di readMaybe. Il primo di questi è risolto esattamente nello stesso modo in cui, come nel caso case, ma per il secondo, leggere singolarmente,

parse xs (readMaybe -> Nothing) = Left "Syntax error" 

non c'è proprio nessun indizio cosa è che non si riescono a leggere, e nessuna ragione per credere che sia la stessa cosa della linea sopra.

In genere, non è opportuno utilizzare i modelli di visualizzazione a meno che non vi sia un solo risultato di interesse. Sono la sintassi sbagliata se si desidera eseguire un calcolo intermedio una volta, ma analizzare il risultato in più di un caso. Sono felice di rimanere nel registro che li considero una disfunzione per questo motivo.

+0

Ok, grazie. Terrò il caso. – Rnhmjoj

+0

I pattern di vista sono molto utili con una funzione con molti casi, ma i casi vengono eseguiti con funzioni che restituiscono un valore Forse e non si esegue mai la corrispondenza con il tipo intermedio. Cose come 'f x | Solo y <- g0 x = ...; Solo y <- g1 x = ... 'versus' f (g0 -> Proprio y); f (g0 -> Proprio y) '- quest'ultimo è molto più bello perché non associa una variabile inutile (' x' nel primo caso). – user2407038

+1

Vale certamente la pena supportare l'abbinamento di modelli che utilizza calcoli intermedi. Il problema è che i pattern di visualizzazione danno un buon supporto solo a questo stile Just-or-bust. Dovremmo essere in grado di avere più di un morso al risultato di una computazione intermedia senza dover lasciare il lato sinistro.Ma sono d'accordo sul fatto che la denominazione extra gratuita è fastidiosa, quindi potrebbe essere utile avere qualche notazione più compatta (quando il calcolo intermedio dipende da una sola variabile di pattern ed è abbinato una sola volta) e voglio anche schemi non lineari invece di un nome extra e un guardia per l'uguaglianza. – pigworker

Problemi correlati