2013-03-14 9 views
7

Diciamo che ho una funzione che esegue alcuni calcoli, con diversi pattern; implementato sotto forma di abbinamento di modelli.Haskell consente un'espressione let per più corrispondenze di pattern?

La maggior parte di questi schemi fa (insieme ad altre cose diverse da una all'altra) un trattamento su un parametro, per il quale utilizzo una variabile intermedia in un'espressione let. Ma trovo davvero ridondante avere lo stesso let su molti modelli, e mi chiedo se c'è un modo per definire uno let per diversi pattern?

Ecco un esempio del mio duplicato let:

data MyType a = Something a | Another Int [a] 

myFunc (Something x) = -- return something, this isn't the point here 
myFunc (Another 0 xs) = 
    let intermediary = some $ treatment xs 
    in doSthg intermediary 1 
myFunc (Another 1 (x:xs)) = 
    let intermediary = some $ treatment xs 
    in doSthg1 intermediary 1 x 
myFunc (Another 2 (x:x':xs)) = 
    let intermediary = some $ treatment xs 
    in doSthg2 intermediary 2 x x' 

Si può vedere che il parametro xs è sempre presente quando lo uso per intermediary, e questo potrebbe essere la fattorizzazione. Potrebbe facilmente essere ottenuto utilizzando una funzione di supporto, ma mi chiedevo se quello che sto chiedendo è possibile senza uno. Per favore, cerca di mantenerlo semplice per un principiante, e spero che il mio esempio sia abbastanza chiaro.

+2

No! Devo usare una funzione separata e passarla come parametro esplicitamente per calcolare il codice ripetuto. Per quanto riguarda Haskell, le precedenti occorrenze di 'xs' sono variabili completamente diverse (perché hanno siti di legame diversi). – luqui

+0

Grazie! Ora ho un'altra domanda: intendevi che la terza e la quarta equazione non corrispondono mai? Perché 'xs' corrisponde a qualsiasi lista ... Hai invertito l'ordine delle equazioni? – yatima2975

+0

Ho scritto questo per illustrare che 'xs' viene estratto dalla corrispondenza del pattern in diversi pattern ma non ha sempre lo stesso significato (altrimenti la corrispondenza del pattern non avrebbe alcun interesse: ci sarebbe solo un pattern). Ciò che è stato fatto con questo esempio non è importante; ma nel mio codice "y" viene sostituito con valori reali, quindi i modelli successivi corrispondono. Ma hai ragione di nuovo, quindi lo modificherò con un tipo concreto per rendere l'intera cosa più comprensibile. –

risposta

7

Questo particolare problema può essere risolto come segue:

myFunc2 (Something x) = returnSomething x 
myFunc2 (Another n ys) = 
    let xs = drop n ys 
     x = head ys 
     x' = head (tail ys) 
     intermediate = some $ treatment xs 
    in case n of 
     0 -> doSomething intermediate n 
     1 -> doSomething1 intermediate n x 
     2 -> doSomething2 intermediate n x x' 

Grazie alla valutazione pigra x e x' saranno valutate solo se è necessario il loro valore.

Tuttavia - e questo è comunque un grande! - il tuo codice genererà un errore di runtime quando proverai a chiamare myFunc2 (Another 2 []) (e se doSomething2 usa effettivamente x!) perché per scoprire cosa sia x, dobbiamo valutare head ys - e questo si bloccherà per una lista vuota. Anche il codice che hai fornito come esempio non funzionerà (un altro errore di runtime) per Another 2 [] poiché non esiste uno schema corrispondente, ma è più semplice fornire un caso di ripiego.

Questo potrebbe non essere un problema se si controlla l'input e si assicura sempre che l'elenco in Another sia sufficientemente lungo, ma è importante essere a conoscenza di questo problema!

+0

Questo non è un problema nel mio codice in quanto gli oggetti 'Altro' non possono essere compilati con liste vuote. +1, fa il trucco molto bene –

+0

@tehinternetsismadeofcatz: L'intero problema ha un forte "interprete per un linguaggio di stack": provalo, quindi se compili correttamente, corri a destra - il tipo di sistema non lo è (ma è vicino!) abbastanza forte da esprimere ciò che tu * sai * sugli input. Potresti anche considerare di cambiare il tuo 'MyType' per esprimere le cose che sai sugli argomenti in modo più chiaro, ma è molto lavoro ... – yatima2975

Problemi correlati