Operator kropki w Haskell: Potrzebujesz więcej wyjaśnień
Próbuję zrozumieć, co operator kropki robi w tym kodzie Haskella:
sumEuler = sum . (map euler) . mkList
Cały kod źródłowy znajduje się poniżej.
Moje zrozumienie
Operator kropki przyjmuje dwie funkcje sum
oraz wynik map euler
i wynik mkList
jako dane wejściowe.
Ale sum
to nie jest funkcja, to jest argument funkcji, prawda? Co tu się dzieje?
Również, co robi (map euler)
?
Kod
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
6 answers
Mówiąc prościej, .
jest składem funkcji, tak jak w matematyce:
f (g x) = (f . g) x
W Twoim przypadku tworzysz nową funkcję, sumEuler
, która może być również zdefiniowana w następujący sposób:
sumEuler x = sum (map euler (mkList x))
Styl w twoim przykładzie nazywa się stylem" point-free " - argumenty funkcji są pomijane. To sprawia, że w wielu przypadkach kod jest jaśniejszy. (Może być ciężko grok za pierwszym razem, ale przyzwyczaisz się do tego po pewnym czasie. Jest to częsty idiom Haskella.)
Jeśli jesteś wciąż zdezorientowany, może pomóc w powiązaniu .
z czymś w rodzaju uniksowej rury. Jeśli wyjście f
staje się wejściem g
, A wyjście staje się wejściem h
, napiszesz to w wierszu 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, gdy, powiedzmy, przetwarzamy listę. Zamiast jakiejś nieporęcznej konstrukcji jak map (\x -> x * 2 + 10) [1..10]
, możesz po prostu napisać (+10) . (*2) <$> [1..10]
. (I, jeśli chcesz zastosować tę funkcję tylko do pojedynczej wartości; (+10) . (*2) $ 10
. Konsekwentnie!)
Haskell wiki ma dobry artykuł z bardziej szczegółowymi informacjami: http://www.haskell.org/haskellwiki/Pointfree
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-26 05:54:00
sum
jest funkcją w preludium Haskella, a nie argumentem sumEuler
. Posiada Typ
Num a => [a] -> a
Operator składu funkcji .
mA typ
(b -> c) -> (a -> b) -> a -> c
Więc mamy
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
Zauważ, że Int
jest instancją Num
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-10 20:02:00
The . operator komponuje funkcje. Na przykład,
a . b
Gdzie a i b są funkcjami jest nową funkcją , 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 takie samo jak:
sumEuler myArgument = sum (map euler (mkList myArgument))
Ale mam nadzieję, że łatwiejsze do odczytania. Powodem, dla którego istnieją pareny wokół mapy Eulera jest to, że wyjaśnia to, że złożone są 3 Funkcje: suma, Mapa euler i mkList - Mapa Eulera jest funkcją pojedynczą.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-28 04:08:09
The . operator jest używany do składu funkcji. Podobnie jak matematyka, jeśli masz funkcje f (x) i g (x) f . g staje się f (g (x)).
Map jest wbudowaną funkcją, która stosuje funkcję do listy. Poprzez umieszczenie funkcji w nawiasach funkcja jest traktowana jako argument. Termin na to to currying . Powinieneś to sprawdzić.
To, co robi, to to, że przyjmuje funkcję z dwoma argumentami, stosuje argument Eulera. / align = "left" / a rezultatem jest nowa funkcja, która przyjmuje tylko jeden argument.
Sum . (Mapa Eulera). mkList jest w zasadzie fantazyjnym sposobem na złożenie tego wszystkiego razem. Muszę powiedzieć, że mój Haskell jest trochę zardzewiały, ale może uda Ci się złożyć tę ostatnią funkcję samodzielnie?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-10 17:08:08
Operator kropki stosuje funkcję po lewej (sum
) do wyjścia funkcji po prawej. W Twoim przypadku łączysz ze sobą kilka funkcji-przekazujesz wynik mkList
do (map euler)
, a następnie przekazujesz wynik tego do sum
.
ta strona ma dobre wprowadzenie do kilku pojęć.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-10 17:09:09
Operator kropki w Haskell
Próbuję zrozumieć, co operator kropki robi w tym kodzie Haskella:
sumEuler = sum . (map euler) . mkList
Krótka odpowiedź
Odpowiednik kodu bez kropek, czyli po prostu
sumEuler = \x -> sum ((map euler) (mkList x))
Lub bez lambdy
sumEuler x = sum ((map euler) (mkList x))
Ponieważ kropka (.) wskazuje skład funkcji.
Dłuższa odpowiedź
Najpierw uprośćmy częściowe zastosowanie euler
do map
:
map_euler = map euler
sumEuler = sum . map_euler . mkList
Teraz mamy tylko kropki. Na co wskazują te kropki?
From the source:
(.) :: (b -> c) -> (a -> b) -> a -> c (.) f g = \x -> f (g x)
Zatem (.)
jest operatorem składowym .
Skomponuj
W matematyce możemy zapisać skład funkcji, f (x) i g (x), czyli f(g(x)), jako
(f ∘ g) (x)
Które można odczytać jako "F złożone z g".
Więc w Haskell, f ∘ g, lub F złożone z g, można zapisać:
f . g
Skład jest asocjacyjny, co oznacza, że f (g (h (x))), zapisany operatorem kompozycji, może bez niejednoznaczności pominąć nawiasy.
Czyli z (f ∘ g) ∘ H jest równoważny do F ∘ (g ∘ h), możemy po prostu napisać F ∘ g ∘ s.
Krąży wstecz
Wracając do naszego wcześniejszego uproszczenia, to:
sumEuler = sum . map_euler . mkList
Oznacza po prostu, że sumEuler
jest nieujemnym składem tych funkcji:
sumEuler = \x -> sum (map_euler (mkList x))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-28 04:06:22