Próbuję omówić instancję aplikacyjną programu Reader, dopasowując definicję typu do kilku przykładów. Jednym z problemów jest to, że nie wiem, jak używać mojego nowego typu programu Reader.
Moja definicja czytelnika to
newtype R r a =
R { run :: r -> a }
Definicja typu dla (<*>)
jest
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Specjalnie dla typu czytającego staje się to:
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
Więc kiedy próbuję:
(<*>) (+) (*2) 5 -- seems equivalent to using Reader since the types match
w REPL dostaję 15
. Myślę, że to dlatego, że oblicza (2*5) + 5
.
Jak mogę to zrobić z moim nowym typem czytnika? I jest a
widzisz w
(r -> a -> b)
to samo a
dostajesz od (r -> a)
czy też coś nie rozumiem?
Odpowiedzi:
4 dla odpowiedzi № 1jak powiedziałem w komentarzach, masz w zasadzie wszystko, czego potrzebujesz - brakujący bit to tylko kwestia techniczna zawijania / rozpakowywania funkcji z R
konstruktor.
ok, oto jak tworzysz swój R
do a Applicative
instancja:
instance Applicative (R r) where
pure a = R (_ -> a)
(R f) <*> (R a) = R (r -> (f r) (a r))
i tak to:
(<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
to przekłada się na:
(<*>) :: R r (a -> b) -> R r a -> R r b
gdy już to zrobisz, wywołanie odpowiednika twojego przykładu obejmuje po prostu zawijanie / rozpakowywanie funkcji z konstruktora:
run (R (+) <*> R (*2)) 5
w przypadku, gdy pojawi się ostrzeżenie o pliku Functor
przykład: potrzebujesz tego też:
instance Functor (R r) where
fmap f (R a) = R (r -> f (a r))