2011-08-02 3 views
4

Рассмотрите следующее определение функции в ghci.Путаница о функциональном составе в Haskell

let myF = sin . cos . sum 

где,. означает композицию из двух функций (правая ассоциативная). Это я могу назвать

myF [3.14, 3.14] 

и он дает мне желаемый результат. По-видимому, он передает список [3.14, 3.14] для функции «sum», а его «результат» передается в cos и так далее и далее. Однако, если я делаю это интерпретатор

let myF y = sin . cos . sum y 

или

let myF y = sin . cos (sum y) 

потом столкнуться с проблемами. Изменение этого в следующем дает мне желаемый результат.

let myF y = sin . cos $ sum y 

или

let myF y = sin . cos . sum $ y 

тип (.) Свидетельствует о том, что не должно быть проблемой со следующей формы, так как сумма «у» является также функцией (это нет? После того, как все- все функции в Haskell?)

let myF y = sin . cos . sum y -- this should work? 

что более интересно, что я могу заставить его работать с двумя (или много) аргументов (думаю прохождения списка [3.14, 3.14], как два аргумента х и у), Я должен написать следующие

let (myF x) y = (sin . cos . (+ x)) y 
myF 3.14 3.14 -- it works! 
let myF = sin . cos . (+) 
myF 3.14 3.14 -- -- Doesn't work! 

Существует некоторая дискуссия по HaskellWiki относительно этой формы, которую они называют «PointFree» форма http://www.haskell.org/haskellwiki/Pointfree. Прочитав эту статью, я подозреваю, что эта форма отличается от состава двух лямбда-выражений. Я смущаюсь, когда пытаюсь провести линию, разделяющую оба эти стиля.

+4

Неверно, что «все функции в Haskell». Конал Эллиот [большое обсуждение этого в своем блоге] (http://conal.net/blog/posts/everything-is-a-function-in-haskell). –

ответ

9

Давайте рассмотрим types. Для sin и cos мы имеем:

cos, sin :: Floating a => a -> a 

Для sum:

sum :: Num a => [a] -> a 

Теперь sum y получается, что в

sum y :: Num a => a 

который является значение, а не функция (вы могли бы назвать это функция без аргументов, но это очень сложно, и вам также нужно назвать функции () -> a - была дискуссия где-то об этом, но я не могу найти ссылку сейчас - Conal говорил об этом).

Во всяком случае, пытается cos . sum y не будет работать, потому что . ожидает, обе стороны имеют типы a -> b и b -> c (подпись (b -> c) -> (a -> b) -> (a -> c)) и sum y не могут быть записаны в этом стиле. Вот почему вам нужно включить круглые скобки или $.

Что касается точки свободного стиля, Simples рецепт перевода заключается в следующем:

  • принять вы действуете и переместить последний аргумент функции в конце выражения, разделенные функции приложения. Например, в случае mysum x y = x + y у нас есть y в конце, но мы не можем удалить его прямо сейчас. Вместо этого, переписывая как mysum x y = (x +) y, он работает.
  • удалите указанный аргумент. В нашем случае повторите до тех пор, пока у вас не будет больше аргументов. Здесь mysum = (+)

(я выбрал простой пример, для более запутанных случаев вы будете использовать flip и другие)

+0

Привет, Михай. Спасибо за это. Если вы можете найти ссылку, сообщите мне. Заранее спасибо. – Dilawar

+0

Что может помочь сделать это еще более ясным, это посмотреть на тип '.', который является' (b -> c) -> (a -> b) -> (a -> c) '. –

+0

Обновлено по ссылке и подписи для '.' как @Antal S-Z –

6

No, sum y не является функцией. Это номер, как и sum [1, 2, 3]. Поэтому вполне понятно, что вы не можете использовать оператор компоновки функций (.).

Не все в Haskell являются функциями.

+0

Я думал, что числа являются функциями с аргументом void. – eternalmatt

+0

@eternalmatt: прочитайте сообщение в блоге Antal S-Z, связанное в комментариях выше. – hammar

3

Обязательным загадочное ответ: (пространство) связывает более плотно, чем .

Большинство пропусков в Haskell можно считать очень высокой фиксацией $ (функция «применить»). w x . y z в основном такая же, как (w $ x) . (y $ z)

Когда вы первый изучения $ и . вы также должны убедиться, что вы узнаете о (пробел), а также, и убедитесь, что вы понимаете, как семантику языка неявно скобки вещи таким образом, чтобы не могут (сначала краснеть) проявляться интуитивно.