Почему делает pointfree версию этой функции, похожи на это?

Я играл вокруг с Haskell немного, включая осуществление функциями записи в форме без точек. Вот функция в качестве примера:

dotProduct :: (Num a) => [a] -> [a] -> a
dotProduct xs ys = sum (zipWith (*) xs ys)

Я хотел бы записать эту функцию в форме без точек. Вот пример, который я нашел в другом месте:

dotProduct = (sum .) . zipWith (*)

Однако я не понимаю, почему форма без точек похожа (sum .) . zipWith (*) вместо sum . zipWith (*). Почему сумма в скобках, и имейте 2 оператора состава?

13
задан guhou 26 June 2010 в 11:53
поделиться

2 ответа

dotProduct xs ys = sum (zipWith (*) xs ys)             -- # definition

dotProduct xs    = \ys -> sum (zipWith (*) xs ys)      -- # f x = g <=> f = \x -> g
                 = \ys -> (sum . (zipWith (*) xs)) ys  -- # f (g x) == (f . g) x
                 = sum . (zipWith (*) xs)              -- # \x -> f x == f
                 = sum . zipWith (*) xs                -- # Precedence rule

dotProduct       = \xs -> sum . zipWith (*) xs         -- # f x = g <=> f = \x -> g
                 = \xs -> (sum .) (zipWith (*) xs)     -- # f * g == (f *) g
                 = \xs -> ((sum .) . zipWith (*)) xs   -- # f (g x) == (f . g) x
                 = (sum .) . zipWith (*)               -- # \x -> f x == f

(сумма) - это раздел. Он определяется как

(sum .) f = sum . f

Любые бинарные операторы могут быть записаны так, например, карта (7 -) [1,2,3] == [7-1, 7-2, 7-3] .

19
ответ дан 1 December 2019 в 19:58
поделиться

Ответ КенниТМ отличный, но все же я хотел бы предложить другую точку зрения:

dotProduct = (.) (.) (.) sum (zipWith (*))
  • (.) f g применяет f к результату g с одним аргументом
  • (.) (.) (.) f g применяет f к результату g при двух аргументах
  • (.) (.) ((.) (.) (.)) f g применяет f к результату g при трёх аргументах
  • ...
  • Может делать (.~) = (.) (.) (.) , (.~~) = (.) (.) (.~) , (.~~~) = (.) (.) (.~~) и теперь let foo a b c d = [1..5]; (.~~~) сумма foo 0 0 0 0 приводит к 15.
    • Но я бы этого не сделал. Это, вероятно, сделает код нечитаемым. Просто будьте полны точки.
  • TypeCompose Конала предоставляет синоним (.) называется result. Возможно, это название более полезно для понимания того, что происходит.
    • fmap также работает вместо (.) , если импортировать соответствующие экземпляры (import Control.Applicative сделает это), но его тип более общий и, следовательно, возможно, более запутанный.
  • Концепция «слияния» Конала (не путать с другими вариантами использования «слияния») в некотором роде связана, и имхо предлагает хороший способ создания функций. Более подробно в этом длинном Google Tech Talk, который Конал дал
13
ответ дан 1 December 2019 в 19:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: