Пожалуй, лучше всего сделать, это думать о двух простых функций:
f :: a -> (b -> c)
g :: (a -> b) -> c
Давайте посмотрим на эти функции, в свою очередь.
Первая функция, f
, принимает один параметр типа a
и возвращает функцию типа b -> c
. Другими словами, вы могли бы написать что-то вроде следующего, предполагая x :: a
, y :: b
и z :: c
:
f :: a -> (b -> c)
f x = f'
where f' :: b -> C
f' y = z
Другой способ, чтобы написать подпись f
как:
f :: a -> b -> c
Это работает, потому что по умолчанию мы связываем ->
направо. Это также дает нам еще один эквивалентный способ понимания: f
: можно подумать о функции, которая принимает два параметра типа a
и b
и производит результат типа c
.
Вторая функция, g
принимает один аргумент, который является функцией типа a -> b
.
g :: (a -> b) -> c
g h = z
where h :: a -> b
Таким образом, они отличаются друг от друга.
Применяя это к вашим функциям, первая функция принимает 4 значения типа Int
и возвращает Int
. Вторая функция принимает единственную функцию типа ((Int -> Int) -> Int) -> Int
, и это функция, которая выполняет третью функцию типа (Int -> Int)
и производит Int
и т. Д.