There is a lot of complexity hiding behind the scenes in the form of invisible type arguments. What happens if we write these arguments out with -XTypeApplications
. I have shortened some of the names.
The following twice
is instantiated at twice @Int
whose type is second-order.
one :: Int
one = twice (+ 1) 0
^^^^^
|
twice @Int
:: (Int -> Int)
-> (Int -> Int)
When you apply twice
(order-3) to twice
(order-2) the type signature becomes more complicated.
two :: Int
two = twice twice (+ 1) 0
^^^^^ ^^^^^
| |
| twice @Int
| :: (Int -> Int)
| -> (Int -> Int)
|
twice @(Int->Int)
:: ((Int->Int) -> (Int->Int))
-> ((Int->Int) -> (Int->Int))
And so forth, when you have twice twice twice
they are order-4, order-3 and order-2 respectively:
three :: Int
three = twice twice twice (+ 1) 0
^^^^^ ^^^^^ ^^^^^
| | |
| | twice @Int
| | :: (Int -> Int)
| | -> (Int -> Int)
| |
| twice @(Int->Int)
| :: ((Int->Int) -> (Int->Int))
| -> ((Int->Int) -> (Int->Int))
|
twice @((Int->Int)->(Int->Int))
:: (((Int->Int)->(Int->Int)) -> ((Int->Int)->(Int->Int)))
-> (((Int->Int)->(Int->Int)) -> ((Int->Int)->(Int->Int)))
the last example you gave becomes this monstrosity with order-6, order-5, order-4, order-3, order-2 respectively...
{-# Language TypeApplications #-}
five :: Int
five = twice @((((Int->Int)->(Int->Int))->((Int->Int)->(Int->Int)))->(((Int->Int)->(Int->Int))->((Int->Int)->(Int->Int))))
(twice @(((Int->Int)->(Int->Int))->((Int->Int)->(Int->Int))))
(twice @((Int->Int)->(Int->Int)))
(twice @(Int->Int))
(twice @Int)
(+ 1) 0
So this is the type of the first twice
!!
twice @((((Int->Int)->(Int->Int))->((Int->Int)->(Int->Int)))->(((Int->Int)->(Int->Int))->((Int->Int)->(Int->Int))))
:: (((((Int -> Int) -> Int -> Int) -> (Int -> Int) -> Int -> Int)
-> ((Int -> Int) -> Int -> Int) -> (Int -> Int) -> Int -> Int)
-> (((Int -> Int) -> Int -> Int) -> (Int -> Int) -> Int -> Int)
-> ((Int -> Int) -> Int -> Int)
-> (Int -> Int)
-> Int
-> Int)
-> ((((Int -> Int) -> Int -> Int) -> (Int -> Int) -> Int -> Int)
-> ((Int -> Int) -> Int -> Int) -> (Int -> Int) -> Int -> Int)
-> (((Int -> Int) -> Int -> Int) -> (Int -> Int) -> Int -> Int)
-> ((Int -> Int) -> Int -> Int)
-> (Int -> Int)
-> Int
-> Int