Frage

Ich habe versucht, die Funktion zu implementieren

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

, die das Thema diese Frage . Ich habe versucht, dieses ohne explizite Rekursion zu tun . Ich kam mit dem folgenden Code oben

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

Meine Funktion funktionierte nicht, da sie nicht faul waren (was in der Frage erforderlich war), so dass kein upvotes es: -).

Allerdings habe ich noch nicht beendet. Ich habe versucht, die Funktion Punkt frei zu machen, so dass es kürzer sein würde (und vielleicht sogar Kühler). Da die Argumente f und xs sind die letzten, die in dem Ausdruck, den ich sie nur fallen gelassen:

every = liftM (all id) $ sequence $ map 

Aber das hat nicht funktioniert, wie erwartet, in der Tat ist es überhaupt nicht arbeiten:

    [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.

Warum ist das so? Ich hatte den Eindruck, dass es möglich war, einfach Funktionsargumente fällt nachlauf, die im Grunde ist das, was currying geht.

War es hilfreich?

Lösung

Die Definition von $ ist

f $ x = f x

Lassen Sie uns voll parenthesize Ihre Funktion:

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

und Ihre curried Version:

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

Wie Sie bemerkt, sind diese nicht identisch. Sie können nur Funktionsargumente Hinter fallen, wenn sie das letzte, was angelegt sind. Zum Beispiel:

f x = g c x

ist eigentlich

f x = (g c) x

und die Anwendung von (g c) bis x kommt zuletzt, so können Sie schreiben

f = g c

Ein Muster mit der Anwendung Operator $ ist, dass es oft die Zusammensetzung Operator wird. in Punkten freien Versionen. Dies liegt daran,

f $ g $ x

entspricht

(f . g) $ x

Beispiel:

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

kann sich

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

an welcher Stelle Sie xs fallen können:

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

Die Beseitigung der Argument f ist schwieriger, weil sie vor der Zusammensetzung Operator angewendet wird. Lassen Sie uns die Definition von Punkt benutzen http://www.haskell.org/haskellwiki/Pointfree :

dot = ((.) . (.))

Mit Punkten, das ist

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

und ist genau das, was wir alle voll Punkte frei machen müssen:

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

Leider aufgrund von Einschränkungen in dem Haskell Typ-System, das man braucht eine explizite Art Signatur:

every :: (Monad m) => (a -> m Bool) -> [a] -> m Bool
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top