2016-04-01 3 views
2
traverse :: Applicative f => (a -> f b) -> t a -> f (t b) 

Hallo,
viele Funktionen gibt, die ich nicht verstehen kann Unterschrift. Natürlich verstehe ich, dass Traverse zwei Argumente erhält, das erste ist die Funktion.
was bedeutet (a -> f b)? Ich kann (a -> b) verstehen.
Similary, t a, f (t b)Verständnis Unterzeichnung Funktion Verfahrweg in Haskell

Können Sie es mir erklären?

+1

'f' steht für einen Typkonstruktor (denke' f = Maybe') also tut 't' (denke' t = [] ') - kannst du verstehen' (a -> Vielleicht b) -> [a] -> Vielleicht [b]? – Carsten

+1

Wenn du ein Gefühl für diesen Fall bekommen willst, kannst du ein bisschen mit "traverse" spielen (\ a -> wenn sogar ein dann einfach (ein 'div' 2) sonst nichts) [2,4,6]' '(versuche, die Eingabeliste zu ändern);) – Carsten

+0

Danke. Sag mir bitte: t a bedeutet immer [a]? –

Antwort

3

traverse ist eine Klasse-ed-Funktion so leider hängt das Verhalten dieser Funktion davon ab, was genau wir wählen t zu sein. Dies ist nicht ähnlich zu >>= oder fmap. Es gibt jedoch Regeln für sein Verhalten, genau wie in diesen Fällen. Die Regeln sollen die Idee einfangen, dass traverse eine Funktion a -> f b übernimmt, die eine wirkungsvolle Transformation von a zu b ist, und hebt es an, auf einem ganzen "Container" von a s zu arbeiten, die Effekte jeder der lokalen Transformationen sammelnd.

Zum Beispiel, wenn wir Maybe a die Umsetzung von traverse haben

traverse f (Just a) = Just <$> f a 
traverse f Nothing = pure Nothing 

Für Listen

traverse f [a1, a2, ...] = (:) <$> f a1 <*> ((:) <$> f a2 <*> ...)) 

Hinweis sein, wie wir die Tatsache zunutze, sind unter, dass die „Wirkung“ f ist nicht nur ein Funktor, sondern auch anwendungsfähig, so dass wir zwei f-ful Berechnungen machen können, f a und f b und zerschlagen sie zusammen, um f (a, b) zu erhalten. Jetzt wollen wir mit ein paar Gesetzen kommen, die erklären, dass alle Traverse können f auf die Elemente anwenden und das Original t a sichern, während Sie die Effekte auf der Außenseite sammeln. Wir sagen, dass

traverse Identity = Identity -- We don't lose elements 
t . traverse f = traverse (t . f) -- For nicely composing t 
traverse (Compose . fmap g . f) = Compose . fmap (traverse g) . traverse f 

Nun ist diese ziemlich kompliziert aussieht, aber alles was man tun hat ist die Bedeutung der Klärung „Im Grunde genommen geht herum und wendet die lokale Transformation“. All dies läuft darauf hinaus, dass, während Sie können nicht nur die Unterschrift lesen, zu verstehen, was traverse tut, eine OK-Intuition für die Signatur ist

  • Wir bekommen eine lokale, effektvolle Funktion f :: a -> f b
  • A Funktors voller a s
  • wir bekommen eine Funktors voller b durch wiederholtes Auftragen f, ala fmap
  • Alle Effekte von f akkumuliert werden wir bekommen f (t b) so zurückbekommen, nicht nur t b.

Denken Sie daran, traverse kann in einigen seltsamen Weisen verwendet werden. Zum Beispiel ist das Objektiv-Paket voll von Verwendung von traverse mit sehr seltsamen Funktoren mit großer Wirkung.

Als schnellen Test, können Sie herausfinden, wie Sie eine legale traverse verwenden, um fmap für t zu implementieren? Das ist

fmapOverkill :: Traversable f => (a -> b) -> (f a -> f b) 

Oder headMay

headMay :: Traversable t => t a -> Maybe a 

Beide sind Ergebnisse der Tatsache, dass verfahrbaren Instanzen auch Functor und Foldable befriedigen!