Question

I have been inspecting the type of Lens to understand it and have trouble figuring out the resulting type of partial application there.

Initial type is like this: type RefF a b = forall f. Functor f => (b -> f b) -> (a -> f a)

The above type applied for Identity functor becomes like this:

(b -> Identity b) -> (a -> Identity a)

Their modify function is defined like this:

modify :: RefF a b -> (b -> b) -> a -> a
modify r m = runIdentity . r (Identity . m)

I decompose the above definition individually to understand it better.

From above, the type of Identity . m is b -> Identity b

I even verified this using the typechecker:

check1 :: (b -> b) -> b -> Identity b
check1 m = Identity . m

Now, I try to formulate the type of r (Identity . m). Here is where my mind becomes empty. The actual result of the partial application of r (Identity . m) seems to be a -> Identity a as typechecked below:

check2 :: RefF a b -> (b -> Identity b) -> a -> Identity a
check2 r che = r che

How does one figure this out mentally ? When I try to partially apply che to r, it doesn't seem to fit:

The type of `r` is   : (b -> Identity b) -> (a -> Identity a)
The type of `che` is : (b -> Identity b)

How does one trace out that the partial application of r che is (a -> Identity a)

Was it helpful?

Solution

When I try to partially apply che to r, it doesn't seem to fit:

r has type

(b -> Identity b) -> (a -> Identity a)

which means its first argument needs to have type (b -> Identity b).

che has type

(b -> Identity b)

Just as r required, therefore r che will work and have type (a -> Identity a).

After applied to the third argument, suppose it has been named arg, of modify, this arg has type a, r (Identity . m) arg will have type Identity a, after applied runIdentity on it, the result will have type a.


type RefF a b = forall f. Functor f => (b -> f b) -> (a -> f a)

modify :: RefF a b -> (b -> b) -> a -> a
modify r m = runIdentity . r (Identity . m)

You could infer the type of modify r m like this:

  1. r has type RefF a b, which is (b -> f b) -> (a -> f a)
  2. m has type b->b
  3. Identity has type forall a. a -> Identity a, therefore Identity . m has type b -> Identity b
  4. r (Identity . m) has type a -> Identity a, because f must be Identity
  5. runIdentity has type forall a. Identity a -> a, therefore runIdentity . r (Identity . m) has type a -> a
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top