(<*>) :: f (a -> b) -> fa -> fb
(<*>) = ??? - Можем ли мы определить это с точки зрения возврата и связывания? без использования "ap"
Напомним, что <*>
имеет сигнатуру типа f (a -> b) -> f a -> f b
, а >>
имеет m a -> (a -> m b) -> m b
. Итак, как мы можем вывести m (a -> b) -> m a -> m b
из m a -> (a -> m b) -> m b
?
Чтобы определить f <*> x
с помощью >>=
, первый параметр >>=
должен быть, очевидно, f
, поэтому мы можем записать первое преобразование:
f <*> x = f >>= k -- k to be defined
, где функцияk
принимает в качестве параметра функцию с типом a -> b
и возвращает результат m b
, так что все определение совпадает с сигнатурой типа bind >>=
. Для k
мы можем написать:
k :: (a -> b) -> m b
k = \xf -> h x
Обратите внимание, что функция h
должна использовать x
из f <*> x
, поскольку x
каким-то образом относится к результату m b
например, функция xf
из a -> b
.
Для h x
легко получить:
h :: m a -> m b
h x = x >>= return . xf
Соедините три вышеприведенных определения, и мы получим:
f <*> x = f >>= \xf -> x >>= return . xf
Таким образом, даже если вы не знаете определения ap
, вы все равно можете получить конечный результат, показанный @chi в соответствии с сигнатурой типа.