1
votes
    ((<*>) . (<*>))
    --In GHCi
    :: (a1 -> a2 -> b) -> ((a1 -> a2) -> a1) -> (a1 -> a2) -> b

Why is it in such type? how can it evolve to such type?

    :t ((<*>) .)

    ((<*>) .)
      :: Applicative f => (a1 -> f (a2 -> b)) -> a1 -> f a2 -> f b

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

    ((<*>) . (<*>))
    --from left to right
  1. (<*>) :: Applicative f1 => f1 (a1 -> b1) -> f1 a1 -> f1 b1;
  2. (.) :: (b -> c) -> (a -> b) -> a -> c;
  3. (<*>) :: Applicative f2 => f2 (a2 -> b2) -> f2 a2 -> f2 b2;

In 2., (a -> b), let 3. f2 (a2 -> b2) = a; therefore, b should be f2 a2 -> f2 b2, (b -> c), replaced by 1., b is f1 (a1 -> b1), c should be f1 a1 -> f1 b1

However, b should be equal to each other, f2 a2 -> f2 b2 = f1 (a1 -> b1) ? how to fit both to each other In GHCi, it seems it replaces f (a -> b) with a1 or a2, then how it goes forward?

1
What dou you mean with "Why is it in such a type"? - Willem Van Onsem
Remember that (->) a is an Applicative. - AJF
Thanks for the comment, I know it's an Applicative, what can it help to evolve the composition? - CLQ0728

1 Answers

1
votes

Your reasoning is correct, as far as I can see.

The next step, as you wrote, is solving

f2 a2 -> f2 b2 = f1 (a1 -> b1)

which is, in prefix notation,

(->) (f2 a2) (f2 b2) = f1 (a1 -> b1)

this means that

(->) (f2 a2) = f1
f2 b2 = a1 -> b1 = (->) a1 b1

so,

(->) (f2 a2) = f1
f2 = (->) a1
b2 = b1

I think you can continue from here. Just remember to interpret x -> y as (->) x y.


Exploiting the above, plus your own findings for a and c, we get:

a = f2 (a2 -> b2) 
  = (->) a1 (a2 -> b2)
  = a1 -> a2 -> b2
  = a1 -> a2 -> b1

c = f1 a1 -> f1 b1
  = (->) (f2 a2) a1 -> (->) (f2 a2) b1
  = (f2 a2 -> a1) -> (f2 a2 -> b1)
  = ((->) a1 a2 -> a1) -> ((->) a1 a2 -> b1)
  = ((a1 -> a2) -> a1) -> (a1 -> a2) -> b1

a -> c =
  = (a1 -> a2 -> b1) -> ((a1 -> a2) -> a1) -> (a1 -> a2) -> b1

which is the original type (with b renamed as b1 here).