Из главы о функторах, в которой вы узнаете о Haskell для большого блага, Липовача заявляет:
"Когда мы делаем
(+) <$> (+3) <*> (*100)
, мы создаем функцию, которая будет использовать+
для результатов(+3)
и(*100)
и вернет это. Чтобы продемонстрировать на реальном примере, когда мы сделали(+) <$> (+3) <*> (*100) $ 5
, сначала5
был применен к(+3)
и(*100)
, в результате получились8
и500
. Затем+
вызывается с8
и500
, в результате чего508
."
Однако, если я попытаюсь оценить функцию самостоятельно, учитывая это определение для Аппликативного на функторе ((- > ) r):
instance Applicative ((->) r) where
pure x = (\_ -> x)
f <*> g = \x -> f x (g x)
Я прочитал оценку вышеуказанного выражения как:
(\x -> (3 + x) (100 * x)) $ 5
Но я не вижу, как мы можем составлять две частично применяемые двоичные функции как единую лямбду (на самом деле GHCi генерирует бесконечную ошибку типа, пытающуюся привязать ее к переменной). Кроме того, к рабочей интерпретации, если мы посмотрим на определение типа для <$>
, получим:
(<$>) :: Functor f => (a -> b) -> f a -> f b
или, более конкретно, мы можем посмотреть на его подъем как:
(<$>) :: Functor f => (a -> b) -> (f a -> f b)
Учитывая, что наш функтор в этом случае равен ((- > ) r), я могу сделать вывод, что именно это преобразование имеет место при предыдущей оценке (если предположить, что левая ассоциативность происходит сначала вместо правильного ассоциативного приложения 5
):
(\x -> a + b)
где a
= (+ 3)
и b
= (* 100)
. Это функция, которая должна быть возвращена. Однако правильно ли я предполагаю, что это окончательная (грубая) форма?
(\x -> (3 + x) + (100 * x)) $ 5
..., что дает 508.
Я нахожу описание Lipovača более понятным с точки зрения того, как работает выражение, но мой кишок говорит мне, что это не совсем верно для подробных деталей под капотом Haskell. Мне легче думать, что fmap из (+) произошел первым, в результате получилась функция с двумя функторами, которые частично применяют функции, которые принимают общий ввод, а затем мы применили к нему значение. Мы можем сделать это из-за ленивой оценки. Это неправильно?