2012-10-26 5 views
7

Ich habe Schwierigkeiten zu verstehen, wie eine Funktion eine Monade sein kann.Funktion als eine Instanz von Monad

Funktion (->) r ist eine Monade nach einer Erklärung in Control.Monad.Instances:

instance Monad ((->) r) where 
    return x = \_ -> x 
    h >>= f = \w -> f (h w) w 

Auch was Miran Lipovača says darüber macht mich verwirrt:

Die Implementierung für >>= ein wenig kryptisch scheint, aber es ist wirklich nicht all das. Wenn wir >>= verwenden, um einer Funktion einen monadischen Wert zuzuweisen, ist das Ergebnis immer ein monadischer Wert. Wenn wir in diesem Fall eine Funktion einer anderen Funktion zuführen, ist das Ergebnis ebenfalls eine Funktion. Das ist warum das Ergebnis als Lambda beginnt. Alle Implementierungen von isolierten das Ergebnis immer irgendwie vom monadischen Wert und fügten dann die Funktion f zu diesem Ergebnis hinzu. Das gleiche passiert hier . Um das Ergebnis einer Funktion zu erhalten, müssen wir es auf etwas anwenden, weshalb wir (h w) hier tun, um das Ergebnis von der Funktion zu bekommen, und dann wenden wir f an. f gibt einen monadischen Wert zurück, der ist eine Funktion in unserem Fall, also wenden wir ihn auch auf w an.

Die Art Unterschrift (>> =) ist dies: (>> =) :: ma -> (a -> mb) -> mb

Also nehme ich, dass h wie typisiert m a und f als (a -> m b). Wenn eine Funktion m a ist, gibt sie einen Wert a zurück? oder gibt es etwas anderes zurück, das einen a Typ nimmt?

Wenn der nicht-Monade Wert von h-f zugeführt wird, dann erhalten wir: f (h w) sieht gut aus. Da f eine Funktion ist und ihr einziges Argument genommen hat, ist es schon ein Wert, nein? Da es sich um eine monadische Funktion handelt, ist der Wert auch ein monadischer Wert. Warum benötigt es dann einen anderen Wert w? Füttert w nicht zu f something macht es nicht-monadisch, d. H. Es ist keine Funktion mehr, nein? Ich kann auch nicht verstehen, warum f something und h das gleiche Argument w nehmen und verschiedene Werttypen (m a und m b) zurückgeben.

Antwort

10

Zunächst ist hier die Art von (>>=):

(>>=) :: (Monad m) => m a -> (a -> m b) -> m b 

Jetzt, mit m spezialisiert auf ((->) r):

(>>=) :: ((->) r) a -> (a -> ((->) r) b) -> ((->) r) b 

Rewritten mit allen Funktionspfeile Infix:

(>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b) 

Entfernen einige überflüssige Klammern:

(>>=) :: (r -> a) -> (a -> r -> b) -> r -> b 

An diesem Punkt sollte es viel einfacher sein, zu sehen, was los ist: das dritte Argument (vom Typ r) mit dem ersten Argumente verwendet wird, etwas von Typ zu bekommen a, sowohl dann, die zur Folge haben und das dritte Argument werden dem zweiten Argument gegeben, um ein Endergebnis vom Typ b zu erhalten.

So stellt ((->) r) als Monad ein zusätzliches Funktionsargument für jeden Wert in dieser Monade dar, und wenn monadische Werte kombiniert werden, wird das einzelne "zusätzliche" Argument dupliziert und jedem Eingabewert zugewiesen. Im Wesentlichen erzeugt dies eine "Nur-Lese-globale Umgebung" für monadische Werte. Diese Interpretation wird explizit als die Reader Monade zur Verfügung gestellt, die nur ein Wrapper um ((->) r) ist.

+0

Danke. Alles ist klar! – amemus

5

Es ist vielleicht einfacher, diese Monade zu verstehen suchen, was join tut, da eine Monade in äquivalenter Weise definiert werden kann fmap und join statt >>= verwenden.

Die allgemeine Form von join hat den Typ Monad m => m (m b) -> m b, also braucht es einen "zweischichtigen" monadischen Wert und cruncht ihn auf eine Schicht herunter.

Mit der Funktion monad, m ~ (a ->), so hat join den Typ (a -> a -> b) -> (a -> b), also nimmt es eine Funktion von zwei Argumenten und gibt eine Funktion zurück, die nur eine nimmt.

join :: (a -> a -> b) -> (a -> b) 
join f = \x -> f x x 

Wie Sie sehen können, dupliziert es nur das Argument.

Ebenso ist fmap auf Funktionen nur Funktion Zusammensetzung und return ist const.

Ich denke, es ist viel einfacher, diesen Weg zu verstehen, als zu versuchen, Sinn von >>= zu machen.

+0

Während dies nützlich ist, um die Instanz konzeptionell zu verstehen, müssen Sie das Verhalten von '>> =' verstehen, um zu verstehen, was jede Zeile in 'do'-Notation für diese Monade bedeutet. –

+0

@DanBurton: In diesem Fall denke ich eigentlich, dass die 'Applicative' Instanz am einfachsten zu erklären und zu verstehen ist, da die" Umgebung "immer das erste Argument ist und die' Monad' Instanz bis zur Parameterreihenfolge äquivalent ist. –

Verwandte Themen