Looking at the parts that you have,
rab :: r -> (a -> b) ra :: r -> a r :: r
and target type b , you can see that the only way to get output b is to apply rab to two arguments.
Reader rab <*> Reader ra = Reader $ \r -> rab _ _
Now the first hole is of type r , and you have only one r in the region.
Reader rab <*> Reader ra = Reader $ \r -> rab r _
The remaining hole is of type a . The only a that you have in scope is the return value of ra ,
Reader rab <*> Reader ra = Reader $ \r -> rab r (ra _)
Argument
and ra should be r , for which again you have only one choice.
Reader rab <*> Reader ra = Reader $ \r -> rab r (ra r)
Note that rab and ra both take r as an argument. All stages of compiled Reader computing have access to the same environment.
By the way, this definition makes <*> equivalent to the famous S combinator (and pure is K ).
source share