Хорошо, вместо использования автоматического c метода для вывода типа, который я думал, возможно, вам будет интересен более интуитивный ответ:
Как я уверен, вы знаете, map . foldr
- это эквивалентно (\x -> map (foldr x))
. Давайте начнем с этого.
Каким должен быть тип x
? Ну, поскольку это первый параметр foldr
, он должен выглядеть как функция, которая принимает некоторое значение, некоторый аккумулятор и возвращает что-то того же типа, что и аккумулятор (по определению foldr
). Таким образом:
x :: (a -> b -> b)
Теперь, когда у нас есть тип первого параметра, давайте посмотрим на остальные.
После применения (foldr x)
мы возвращаем функцию, которая все еще ожидает начальное значение аккумулятора, а затем - любой складываемый тип и возвращает значение того же типа, что и аккумулятор (например, сумма каждого элемента в списке).
Итак, тип (foldr x)
должен быть
Foldable t => b -> t a -> b
Хорошо, но мы еще не закончили, посмотрим, что произойдет с использованием map сейчас же.
карта должна сначала получить функцию (по определению). Возвращаемое значение (foldr x)
выглядит так, что означает, что это использование карты учитывает, что (b -> t a -> b)
является типом функции, которую необходимо применить к каждому элементу списка.
Может быть, это яснее записано как (b -> (t a -> b))
. Таким образом, это использование карты предполагает, что ей дана функция, которая принимает некоторый ввод типа b и возвращает функцию, которая сама принимает складную a
и возвращает b
.
Хорошо, мы почти там. Теперь для map все еще нужен другой аргумент: список, элементы которого имеют тот же тип, что и входные данные функции, к которой она будет применяться. Таким образом, поскольку функция, которую мы хотим применить (результат (foldr x)
), принимает b
, наше использование карты займет [b]
.
Итак, теперь у нас есть:
(a -> b -> b) -> [b] -> …
Нам просто не хватает типа выходного значения этой композиции функций, которая является типом выходного значения этого спецификатора c использование карты. Поскольку функция, применяемая с map, возвращает что-то типа (t a -> b)
, то список вещей, которые мы, очевидно, вернем, будет иметь тип [t a -> b]
.
Так что в итоге у вас будет
Foldable t => (a -> b -> b) -> [b] -> [t a -> b]
как тип map . foldr
.