guh*_*hou 13 haskell pointfree
我一直在玩Haskell,包括练习以无点形式编写函数.这是一个示例函数:
dotProduct :: (Num a) => [a] -> [a] -> a
dotProduct xs ys = sum (zipWith (*) xs ys)
Run Code Online (Sandbox Code Playgroud)
我想以无点形式编写这个函数.这是我在其他地方找到的一个例子:
dotProduct = (sum .) . zipWith (*)
Run Code Online (Sandbox Code Playgroud)
但是,我不明白为什么无点形式看起来像(sum .) . zipWith (*)而不是sum . zipWith (*).为什么括号中的和有2个组合运算符?
ken*_*ytm 19
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
Run Code Online (Sandbox Code Playgroud)
这(sum .)是一节.它被定义为
(sum .) f = sum . f
Run Code Online (Sandbox Code Playgroud)
任何二元运算符都可以这样写,例如map (7 -) [1,2,3] == [7-1, 7-2, 7-3].
yai*_*chu 13
KennyTM的答案非常好,但我还想提供另一个观点:
dotProduct = (.) (.) (.) sum (zipWith (*))
Run Code Online (Sandbox Code Playgroud)
(.) f g适用f于g给定一个参数的结果(.) (.) (.) f g适用f于g给定两个参数的结果(.) (.) ((.) (.) (.)) f g适用f于g给定三个参数的结果(.~) = (.) (.) (.),(.~~) = (.) (.) (.~),(.~~~) = (.) (.) (.~~)现在let foo a b c d = [1..5]; (.~~~) sum foo 0 0 0 0导致15.
TypeCompose提供了(.)被叫的同义词result.也许这个名字对于了解正在发生的事情更有帮助.
fmap(.)如果导入相关实例(import Control.Applicative会这样做),也可以代替,但它的类型更通用,因此可能更令人困惑.