2010-09-24 9 views
13

Esiste un'elegante notazione per Esaminare gli argomenti di una funzione fuori servizio in Haskell?Corrispondenza fuori servizio in Haskell

Ad esempio, se si desidera dividere 2 per tutti gli elementi di una lista, è possibile scrivere

map ((/) 2) [1,2,3,4,5] 

Tuttavia a dividere tutti gli elementi di una lista che sembra è necessario definire una funzione anonima

map (\x -> x/2) [1,2,3,4,5] 

Le funzioni anonime diventano rapidamente ingombranti in casi più complessi. Sono consapevole che in questo caso la mappa ((*) 0.5) [1,2,3,4,5] funzionerebbe bene, ma sono interessato a sapere se Haskell ha un modo più elegante di argomentare argomenti di una funzione guasto?

+0

'flip' e i backtick sono buoni con semplicemente usando la funzione infisso (come delnan indica). –

risposta

16

In questo caso particolare:

Prelude> map (/2) [1..5] 
[0.5,1.0,1.5,2.0,2.5] 

Non solo è possibile utilizzare un operatore infisso in funzione del prefisso comune, si può anche parzialmente applicarlo in forma infissa. Allo stesso modo, il primo esempio sarebbe meglio essere scritto come map (2/) [1..5]

Inoltre, c'è flip, che non è così elegante, ma ancora la migliore opzione disponibile per le funzioni ordinarie (quando non si vuole trasformarli in infisso via apici inversi) :

Prelude> let div' = (/) 
Prelude> div' 2 1 
2.0 
Prelude> flip div' 2 1 
0.5 
+0

Funziona solo con gli operatori? Che dire delle funzioni arbitrarie? – Gabe

+0

@Gabe: come scritto da FUZxxl, funziona anche con le funzioni utilizzate infix (circondandole con i backtick). Fornirei un esempio, ma ne ha già fornito uno. – delnan

+0

Grazie.È un peccato che non ci sia sintassi come f 1 2 # 4 #, che abbia lo stesso effetto di \ x y -> f 1 2 x 4 y. – hosiers

2

per la vostra seconda, lambda è necessario, basta usare come:

map (/2) [1..5] 

la forma (/ 2) significa semplicemente, che si desidera accedere al secondo param di un operatore. È anche possibile con il primo argomento (2/). Questa è chiamata sezione ed è un trucco molto utile, non solo nel campo del golf. È inoltre possibile utilizzarlo nelle funzioni di prefisso, se si utilizzano infisso:

map (`div` 2) [1..5] 

Nei casi più difficili, come 3 o più argomenti, si suppone di utilizzare lambda, in quanto diventa più leggibile la maggior parte delle volte.

2

Penso che stiate cercando una soluzione generalizzata, come nello schema cut. Destra?

C'è la funzione flip che inverte i primi 2 argomenti di una funzione. Potrebbero esserci altre funzioni che svolgono un compito simile (non sono ancora troppo bravo con Haskell ...).

+1

'flip' non inverte l'elenco degli argomenti. Semplicemente capovolge i primi due, considera questo: 'flip (.) :: (a -> b) -> (b -> c) -> a -> c'. -1 – fuz

0

ho incontrato un very similar issue me di recente, e non ero in grado di trovare una soluzione elegante altro che usare una funzione di supporto per farlo:

dbfunc f b c = (\a -> liftIO $ f a b c) 
deleteAllRows = do 
    ask >>= dbfunc run "delete from t1" [] 

Almeno questo modello è abbastanza comune in HDBC che dbfunc è riutilizzabile

+0

'ask >> = liftIO. (capovolgi (flip run) "cancella da t1" []) ' – is7s

+0

Per certi valori di elegante ;-) – Gaius

Problemi correlati