Frage

Ich versuche zu verstehen, was der Punkt-Operator in diesem Haskell Code tun:

sumEuler = sum . (map euler) . mkList

Der gesamte Quellcode ist unten.

Mein Verständnis

Der Punkt-Operator nimmt die beiden Funktionen sum und das Ergebnis map euler und das Ergebnis des mkList als Eingang.

Aber ist sum keine Funktion es das Argument der Funktion ist, nicht wahr? Also, was ist hier los?

Auch was tut (map euler)?

Code

mkList :: Int -> [Int]
mkList n = [1..n-1]

euler :: Int -> Int
euler n = length (filter (relprime n) (mkList n))

sumEuler :: Int -> Int
sumEuler = sum . (map euler) . mkList
War es hilfreich?

Lösung

Einfach gesagt, . ist Funktion Zusammensetzung, wie in der Mathematik:

f (g x) = (f . g) x

In Ihrem Fall, erstellen Sie eine neue Funktion, sumEuler, die auch wie folgt definiert werden:

sumEuler x = sum (map euler (mkList x))

Der Stil in Ihrem Beispiel „Punkt-free“ Stil genannt wird - die Argumente der Funktion weggelassen. Dies sorgt für klareren Code in vielen Fällen. (Es kann schwierig sein, das erste Mal grok Sie es sehen, aber Sie werden nach einer Weile daran gewöhnen. Es ist ein verbreitetes Haskell Idiom.)

Wenn Sie immer noch verwirrt sind, kann es helfen . zu so etwas wie eine UNIX-Pipe zu beziehen. Wenn f der Ausgang g der Eingang wird, dessen Ausgang wird h der Eingang, dann würden Sie, dass auf der Kommandozeile wie f < x | g | h schreiben. In Haskell, arbeitet . wie die UNIX |, aber "nach hinten" - h . g . f $ x. Ich finde diese Notation als sehr hilfreich, wenn, sagen wir, eine Liste zu verarbeiten. Statt einiger unhandlichen Konstruktion wie map (\x -> x * 2 + 10) [1..10], könnten Sie einfach (+10) . (*2) <$> [1..10] schreiben. (Und wenn Sie wollen nur, dass die Funktion auf einen einzigen Wert anzuwenden;.! Es ist (+10) . (*2) $ 10 Konsistente)

Das Haskell Wiki hat einen guten Artikel mit etwas mehr Detail: http://www.haskell.org/ haskellwiki / Pointfree

Andere Tipps

Die. Operator komponiert Funktionen. Zum Beispiel:

a . b

Wo a und b sind Funktionen ist eine neue Funktion , die b auf seine Argumente ausgeführt wird, dann wird ein auf diesen Ergebnissen. Ihr Code

sumEuler = sum . (map euler) . mkList

ist genau das gleiche wie:

sumEuler myArgument = sum (map euler (mkList myArgument))

aber hoffentlich leichter zu lesen. Der Grund gibt es Pars um Karte euler ist, weil es deutlicher macht, dass es 3 Funktionen zusammensetzt: Summe Karte euler und mkList -. Karte euler ist eine einzige Funktion

sum ist eine Funktion in der Haskell Prelude, kein Argument sumEuler. Es hat den Typ

Num a => [a] -> a

Die Funktion Zusammensetzung Operator . hat Typen

(b -> c) -> (a -> b) -> a -> c

So haben wir

sum                        :: Num a => [a] -> a
map                        :: (a -> b) -> [a] -> [b]
euler                      :: Int -> Int
mkList                     :: Int -> [Int]
(map euler)                :: [Int] -> [Int]
(map euler) . mkList       :: Int -> [Int]
sum . (map euler) . mkList :: Int -> Int

Beachten Sie, dass Int eine Instanz von Num ist.

Die. Operator für Funktions Zusammensetzung verwendet. Genau wie Mathematik, wenn Sie auf die Funktionen f (x) und g (x) f haben. g wird f (g (x)).

Karte ist eine eingebaute Funktion, die eine Funktion auf eine Liste gilt. Indem die Funktion in Klammern wird die Funktion als Argument behandelt. Ein Begriff hierfür ist currying . Sie sollten das nachzuschlagen.

Was ist tut, ist, dass sie eine Funktion nimmt mit sagen zwei Argumente, es das Argument euler gilt. (Karte euler) richtig? und das Ergebnis ist eine neue Funktion, die nur ein Argument.

Summe. (Karte euler). mkList ist im Grunde eine andere Art das alles zusammen zu stellen. Ich muss sagen, mein Haskell ein wenig eingerostet ist, aber vielleicht können Sie diese letzte Funktion zusammengestellt selbst?

Der Punkt-Operator wendet die Funktion auf der linken Seite (sum) mit dem Ausgang der Funktion auf der rechten Seite. In Ihrem Fall sind verketten Sie mehrere Funktionen zusammen - das Ergebnis von mkList vorbei ist, (map euler) und dann vorbei das Ergebnis, das sum. Diese Seite hat eine gute Einführung in einige der Konzepte.

  

Dot Operator in Haskell

     

Ich versuche zu verstehen, was der Punkt-Operator in diesem Haskell Code tun:

sumEuler = sum . (map euler) . mkList

Kurze Antwort

Equivalent Code ohne Punkte, das ist nur

sumEuler = \x -> sum ((map euler) (mkList x))

oder ohne Lambda

sumEuler x = sum ((map euler) (mkList x))

, da der Punkt (.) Zeigt Funktion Zusammensetzung.

Längere Antwort

Lassen Sie uns zuerst die partielle Anwendung von euler zu map vereinfachen:

map_euler = map euler
sumEuler = sum . map_euler . mkList

Jetzt haben wir nur die Punkte. Was wird durch diese Punkte angedeutet?

Von die Quelle :

(.)    :: (b -> c) -> (a -> b) -> a -> c
(.) f g = \x -> f (g x)

So (.) ist die Operator zu komponieren.

Compose

In der Mathematik, könnten wir die Zusammensetzung der Funktionen f (x) und g (x) schreiben, das heißt, f (g (x)), wie

  

(f ∘ g) (x)

, die gelesen werden kann „f mit g zusammengesetzt“.

So in Haskell, f ∘ g oder f mit g zusammengesetzt ist, kann geschrieben werden:

f . g

Zusammensetzung ist assoziativ, was bedeutet, daß f (g (h (x))), mit der Zusammensetzung Operator geschrieben werden, kann ohne Mehrdeutigkeit die Klammern wegzulassen.

Das heißt, da (f ∘ g) ∘ h entspricht f ∘ (g ∘ h), können wir einfach schreiben f ∘ g ∘ h.

Circling zurück

Circling zurück zu unserer früheren Vereinfachung folgt aus:

sumEuler = sum . map_euler . mkList

nur bedeutet, dass sumEuler eine unangewendet Zusammensetzung dieser Funktionen:

sumEuler = \x -> sum (map_euler (mkList x))
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top