Mówiąc prościej, .
jest kompozycją funkcji, tak jak w matematyce:
f (g x) = (f . g) x
W twoim przypadku tworzysz nową funkcję, sumEuler
którą można również zdefiniować w ten sposób:
sumEuler x = sum (map euler (mkList x))
Styl w twoim przykładzie jest nazywany stylem „bez punktów” - argumenty funkcji są pomijane. W wielu przypadkach zapewnia to bardziej przejrzysty kod. (Może to być trudne, gdy zobaczysz go po raz pierwszy, ale po chwili się do tego przyzwyczaisz. To popularny idiom Haskella).
Jeśli nadal jesteś zdezorientowany, pomocne może być odniesienie się .
do czegoś takiego jak potok UNIX. Jeśli f
wyjście staje się g
wejściem, którego wyjście staje się h
wejściem, można to zapisać w linii poleceń, jak f < x | g | h
. W Haskell .
działa jak UNIX |
, ale "wstecz" - h . g . f $ x
. Uważam, że ta notacja jest bardzo pomocna podczas, powiedzmy, przetwarzania listy. Zamiast jakiejś nieporęcznej konstrukcji map (\x -> x * 2 + 10) [1..10]
, możesz po prostu pisać (+10) . (*2) <$> [1..10]
. (A jeśli chcesz zastosować tę funkcję tylko do jednej wartości, to jest (+10) . (*2) $ 10
. Spójne!)
Na wiki Haskell znajduje się dobry artykuł zawierający więcej szczegółów: http://www.haskell.org/haskellwiki/Pointfree
f (g x)
=(f . g) x
”?) Czy coś innego?==
zamiast jeśli chcesz wzorca Haskell.Plik. operator komponuje funkcje. Na przykład,
a . b
Gdzie a i b są funkcjami, to nowa funkcja, która uruchamia b na swoich argumentach, a następnie a na tych wynikach. Twój kod
sumEuler = sum . (map euler) . mkList
jest dokładnie taki sam jak:
sumEuler myArgument = sum (map euler (mkList myArgument))
ale miejmy nadzieję, że łatwiej je przeczytać. Powodem, dla którego wokół map euler są pareny, jest to, że wyjaśnia to, że składane są 3 funkcje: sum , map euler i mkList - map euler to pojedyncza funkcja.
źródło
sum
jest funkcją w Haskell Prelude, a nie argumentem dosumEuler
. Ma swój typNum a => [a] -> a
Operator kompozycji funkcji
.
ma typWięc mamy
euler :: Int -> Int map :: (a -> b ) -> [a ] -> [b ] (map euler) :: [Int] -> [Int] mkList :: Int -> [Int] (map euler) . mkList :: Int -> [Int] sum :: Num a => [a ] -> a sum . (map euler) . mkList :: Int -> Int
Zauważ, że
Int
rzeczywiście jest to instancjaNum
typeklasy.źródło
Plik. operator jest używany do tworzenia funkcji. Podobnie jak matematyka, jeśli masz do funkcji f (x) i g (x) f. g staje się f (g (x)).
mapa to wbudowana funkcja, która stosuje funkcję do listy. Umieszczając funkcję w nawiasach, funkcja jest traktowana jako argument. Określeniem na to jest curry . Powinieneś to sprawdzić.
To, co robi, to to, że przyjmuje funkcję z, powiedzmy, dwoma argumentami, stosuje argument euler. (map euler) prawda? a wynikiem jest nowa funkcja, która przyjmuje tylko jeden argument.
suma . (mapa euler). mkList to po prostu fantazyjny sposób na złożenie tego wszystkiego w całość. Muszę powiedzieć, że mój Haskell jest trochę zardzewiały, ale może możesz sam połączyć tę ostatnią funkcję?
źródło
Krótka odpowiedź
To znaczy równoważny kod bez kropek
sumEuler = \x -> sum ((map euler) (mkList x))
lub bez lambda
sumEuler x = sum ((map euler) (mkList x))
ponieważ kropka (.) wskazuje skład funkcji.
Dłuższa odpowiedź
Najpierw uprośćmy częściowe zastosowanie funkcji
euler
domap
:map_euler = map euler sumEuler = sum . map_euler . mkList
Teraz mamy tylko kropki. Na co wskazują te kropki?
Ze źródła :
Tak
(.)
jest z operatorem tworzenia .Komponować
W matematyce moglibyśmy zapisać skład funkcji, f (x) i g (x), czyli f (g (x)), jako
które można odczytać jako „f składa się z g”.
Zatem w Haskell f ∘ g lub f złożone z g można zapisać:
f . g
Kompozycja jest asocjacyjna, co oznacza, że f (g (h (x))), napisane operatorem kompozycji, może pomijać nawiasy bez żadnej dwuznaczności.
To znaczy, ponieważ (f ∘ g) ∘ h jest równoważne f ∘ (g ∘ h), możemy po prostu napisać f ∘ g ∘ h.
Wracając
Wracając do naszego wcześniejszego uproszczenia, to:
sumEuler = sum . map_euler . mkList
oznacza po prostu, że
sumEuler
jest to niezastosowana kompozycja tych funkcji:sumEuler = \x -> sum (map_euler (mkList x))
źródło
Operator kropkowy stosuje funkcję po lewej stronie (
sum
) do wyjścia funkcji po prawej stronie. W twoim przypadku łączysz ze sobą kilka funkcji - przekazujesz wynikmkList
do(map euler)
, a następnie przekazujesz wynik dosum
. Ta strona zawiera dobre wprowadzenie do kilku pojęć.źródło