2016-05-31 22 views
1

Ich versuche, mich mit der Anwendungs-Instanz für Reader zu befassen, indem ich die Typdefinition mit einigen Beispielen abgleiche. Ein Problem ist, dass ich nicht weiß, wie ich meinen Reader newtype verwenden soll.Wie benutze ich meinen Reader: newtype R r a = R {run :: r -> a}?

Meine Definition von Reader

newtype R r a = 
    R { run :: r -> a } 

Die Typdefinition für (<*>) ist

(<*>) :: Applicative f => f (a -> b) -> f a -> f b 

Specialized für den Reader-Typ wird daraus:

(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b) 

Also, wenn ich versuche:

(<*>) (+) (*2) 5 -- seems equivalent to using Reader since the types match 

in der REPL bekomme ich 15. Ich denke, das ist, weil es (2*5) + 5 berechnet.

Wie würde ich das oben mit meinem Reader newtype tun? Und ist die a Sie in (r -> a -> b) sehen die gleiche a Sie bekommen von (r -> a) oder bin ich etwas missverstanden?

+1

Sie müssen nur packen/entpacken von 'R 'bei der Definition Ihrer' Applicative' -Instanz: '(R f) <*> (R a) = R (\ r -> (fr) (ar))' – Carsten

+1

Falls Sie die Instanz * bereits * haben, müssen Sie die Funktion umbrechen/Werte in 'R' und dann können Sie' run' verwenden: 'run (R (+) <*> R (* 2)) 5' – Carsten

+0

Ich denke, meine Frage war nicht die klarste. Das ist, was ich mich gefragt habe, wird upvote, wenn Sie das als Antwort hinzufügen. Könnte Sie bitten, eine Follow-up-q auf der applicative Instanz obwohl. –

Antwort

4

Wie ich schon sagte in den Kommentaren haben Sie im Grunde alles, was Sie brauchen - das fehlende Bit ist nur die Technik der Verpackung/Entpacken der Funktion aus dem R Konstruktor.

ok hier ist, wie Sie Ihr machen R in eine Applicative Beispiel:

instance Applicative (R r) where 
    pure a   = R (\_ -> a) 
    (R f) <*> (R a) = R (\r -> (f r) (a r)) 

und ja diese:

(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b) 

dann übersetzt in:

(<*>) :: R r (a -> b) -> R r a -> R r b 

, wenn Sie diese haben Der Aufruf, der Ihrem Beispiel entspricht, bezieht sich nur auf das Wrapping/unw die Funktion aus dem Konstruktor rappen:

run (R (+) <*> R (*2)) 5 

falls Sie eine Warnung über eine Functor Instanz erhalten: Sie müssen dies auch:

instance Functor (R r) where 
    fmap f (R a) = R (\r -> f (a r)) 
+0

Frage1) Ich bin verwirrt, warum ': t (Reader (+) <*> Reader (* 2)) ist' Num b => Reader bb'. Kannst du mir bitte erklären oder soll ich ein neues q fragen?Question2) Das erste Argument für '(<*>)' ist 'r (a -> b)' - warum gibt es dann check um '(+)' zu geben, was '(r -> a -> b)' ist? Vielen Dank. –

+0

ist es, weil '(+)' ist 'Num c => c -> c -> c' - so, wenn Sie das' r -> (a -> b) '(das Wesentliche von' R r (a - > b) ') und' (+) '' einstecken, dafür brauchst du 'r ~ c',' a ~ c' und 'b ~ c' - was den Typ (nach dem Umbenennen) ergibt ... btw: der erste Argument zu '<*>' hier ist nicht 'r (a -> b)' - es ist 'R r (a -> b)' – Carsten