Прочитал много похожих тем и так и не понял.
Итак, вопрос в том, чтобы создать функцию, которая имеет определенный тип
например, заданный тип Integer-> Integer
функция, которая имеет этот тип, \x-> x+1
как найти функцию заданного типа с помощью лямбда.
(((Int → a) → a) → b) → b
(a -> b) -> c
a → (a → a)
(b -> c) -> (a -> b) -> a -> c
я решил 4) угадав
Три переменные после лямбда, f имеет тип b->c, g имеет тип a->b и a
:t \f g a -> f (g a)
я действительно не понимаю шаги, которые там вводятся (b-> c), (a-> b) и a. потом угадал порядок
для 1) есть только один ввод, поэтому он должен быть \f-> \g->...
(b -> c) -> (a -> b) -> a -> c
представляет собой функцию с 3 полиморфными параметрами, первые 2 параметра также являются функциями, первый — b -> c
(функция, принимающая b и возвращающая c), а второй — a -> b
(функция, принимающая a и возвращающая b) (см. функции высшего порядка). Лямбда \f g a -> f (g a)
имеет три параметра и реализуется результатом вызова g
с параметром a
, переданным f
.
Один из лучших способов решить эти упражнения на практике — использовать отверстия: написать _
для заполнения дыры и прочитать из GHCi тип этой дыры.
> foo :: (((Int -> a) -> a) -> b) -> b ; foo = _
* Found hole: _ :: (((Int -> a) -> a) -> b) -> b
Дырка - это функция. Тогда воспользуемся лямбдой.
> foo :: (((Int -> a) -> a) -> b) -> b ; foo = \f -> _
* Found hole: _ :: b
* Relevant bindings include
f :: ((Int -> a) -> a) -> b
Отверстие должно быть типа b
. Больше никаких лямбд. Мы не можем создать значение типа b
, если мы каким-то образом не применим f
(обратите внимание на печатный тип f
).
> foo :: (((Int -> a) -> a) -> b) -> b ; foo = \f -> f _
* Found hole: _ :: (Int -> a) -> a
Ах, теперь дыра снова является функцией. Еще одна лямбда.
> foo :: (((Int -> a) -> a) -> b) -> b ; foo = \f -> f (\g -> _)
* Found hole: _ :: a
* Relevant bindings include
g :: Int -> a
Ну а теперь нам нужно произвести a
. С g :: Int -> a
в нашем распоряжении это выглядит просто.
> foo :: (((Int -> a) -> a) -> b) -> b ; foo = \f -> f (\g -> g 42)
Больше никаких дыр - готово.
Обратите внимание, что ваше 2) (a -> b) -> c
невозможно правильно реализовать - нет никакого способа создать c
из этого ввода. Вы можете писать только не завершающие (или вызывающие сбой) программы с этим типом.