Я могу понять основы точечных функций в Haskell:
addOne x = 1 + x
Как мы видим x по обе стороны уравнения, мы его упрощаем:
addOne = (+ 1)
Невероятно, что функции, в которых один и тот же аргумент используется дважды в разных частях, могут быть записаны без точек!
Позвольте мне взять в качестве основного примера функцию average
, написанную как:
average xs = realToFrac (sum xs) / genericLength xs
Может показаться невозможным упростить xs
, но http://pointfree.io/ выходит с:
average = ap ((/) . realToFrac . sum) genericLength
Это работает.
Насколько я понимаю, это означает, что average
совпадает с вызовом ap
для двух функций, состав (/) . realToFrac . sum
и genericLength
К сожалению, функция ap
не имеет никакого отношения ко мне, docs http://hackage.haskell.org/package/base-4.8.1.0/docs/Control-Monad.html#v:ap:
ap :: Monad m => m (a -> b) -> m a -> m b
In many situations, the liftM operations can be replaced by uses of ap,
which promotes function application.
return f `ap` x1 `ap` ... `ap` xn
is equivalent to
liftMn f x1 x2 ... xn
Но запись:
let average = liftM2 ((/) . realToFrac . sum) genericLength
не работает, (дает сообщение об ошибке очень длинного типа, спрашивает, и я его включу), поэтому я не понимаю, что говорят документы.
Как работает выражение ap ((/) . realToFrac . sum) genericLength
? Не могли бы вы объяснить ap
проще, чем документы?