Domanda

Stavo cercando di implementare la funzione

every :: (a -> IO Bool) -> [a] -> IO Bool 

quale era l'argomento questa domanda.Ho provato a farlo senza ricorsione esplicita.Mi è venuta in mente il seguente codice

every f xs = liftM (all id) $ sequence $ map f xs

La mia funzione non ha funzionato poiché non era pigra (cosa richiesta nella domanda), quindi nessun voto positivo :-).

Tuttavia, non mi sono fermato qui.Ho provato a creare la funzione senza punti in modo che fosse più breve (e forse anche più interessante).Fin dalle argomentazioni f E xs sono gli ultimi nell'espressione che li ho appena eliminati:

every = liftM (all id) $ sequence $ map 

Ma questo non ha funzionato come previsto, anzi non ha funzionato affatto:

    [1 of 1] Compiling Main             ( stk.hs, interpreted )

    stk.hs:53:42:
        Couldn't match expected type `[m a]'
               against inferred type `(a1 -> b) -> [a1] -> [b]'
        In the second argument of `($)', namely `map'
        In the second argument of `($)', namely `sequence $ map'
        In the expression: liftM (all id) $ sequence $ map
    Failed, modules loaded: none.

Perché?Avevo l'impressione che fosse possibile semplicemente eliminare gli argomenti finali della funzione, che fondamentalmente è ciò che riguarda il currying.

È stato utile?

Soluzione

La definizione di $ è

f $ x = f x

Mettiamo tra parentesi la tua funzione:

every f xs = (liftM (all id)) (sequence ((map f) xs))

e la tua versione al curry:

every = (liftM (all id)) (sequence map)

Come hai notato, questi non sono identici.Puoi eliminare gli argomenti finali della funzione solo quando sono l'ultima cosa applicata.Per esempio,

f x = g c x

è effettivamente

f x = (g c) x

e l'applicazione di (g c) a x viene per ultima, quindi puoi scrivere

f = g c

Uno schema con l'operatore dell'applicazione $ è che spesso diventa l'operatore di composizione.nelle versioni senza punti.Questo è perché

f $ g $ x

è equivalente a

(f . g) $ x

Per esempio,

every f xs = liftM (all id) $ sequence $ map f xs

può diventare

every f xs = (liftM (all id) . sequence . map f) xs

a quel punto puoi eliminare xs:

every f = liftM (all id) . sequence . map f

Eliminare l'argomento f è più difficile perché viene applicato prima dell'operatore di composizione.Usiamo la definizione di punto da http://www.haskell.org/haskellwiki/Pointfree:

dot = ((.) . (.))

Con i punti, questo è

(f `dot` g) x = f . g x

ed è esattamente ciò di cui abbiamo bisogno per rendere tutti i punti completamente gratuiti:

every = (liftM (all id) . sequence) `dot` map

Purtroppo, a causa delle restrizioni nel sistema di tipi Haskell, questo necessita di una firma di tipo esplicita:

every :: (Monad m) => (a -> m Bool) -> [a] -> m Bool
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top