Considerare le funzioni del tipo a -> b -> c
e i valori applicativi a1, a2 :: (Applicative f) => f a
.
Desidero costruire una funzione che può essere applicata alle funzioni di tipo a -> b -> c
per ottenere i valori di tipo Applicative f :: f c
. Posso fare questo nel modo seguente:
g :: (Applicative f) => (a -> b -> c) -> f c
g = \f -> f <$> a1 <*> a2
(Il lambda esplicita è deliberata, come sto considerando la costruzione di questa funzione a qualsiasi livello, non solo il livello superiore).
Se provo a scrivere g
in stile libero-point:
g = (<$> a1 <*> a2)
ottengo il seguente errore di compilazione:
The operator `<$>' [infixl 4] of a section
must have lower precedence than that of the operand,
namely `<*>' [infixl 4]
in the section: `<$> gen1 <*> gen2'
ho potuto scrivere questa implementazione libera-punto:
g = flip (flip liftA2 a1) a2
ma credo che questo sia le ss leggibile, ed è più semplice per refactoring l'implementazione basata sulla funzione infisso per, ad esempio, aggiungere un altro argomento, che modificare il precedente per utilizzare liftA3
.
Si può scrivere una catena di composizioni:
g = (<*> a2) . (<$> a1)
Questo raggiunge free style punto ed è semplice aggiungere argomenti - ma ottengono anteposto a sinistra invece che aggiunto a destra, così si perde la corrispondenza con la funzione tipo (a -> b -> c)
. Inoltre, con più argomenti si finisce con un'espressione molto più lunga rispetto all'utilizzo di un lambda come nella prima implementazione.
Quindi, c'è un modo carino e teso per scrivere la sezione che desidero o sono bloccato con un lambda?
a Scala si potrebbe avere '_ <$> un b' <*> ma Haskell non ha tale sintassi. –
@ErikAllik Questa è una sintassi interessante! Mi chiedo se qualcuno abbia scritto un'estensione template-haskell per questo. Sarebbe fantastico. – AJFarmar
ma '_' è già stato preso da buchi digitati; forse qualcosa di simile però; sebbene la sintassi lambda sia abbastanza buona. –