我一直认为 pointfree 函数的先决条件是将函数参数获取到定义的末尾。例如
-- This can be made pointfree quite easily:
let lengths x = map length x
let lengths' = map length
-- However this cannot:
let lengthz x = length `map` x
-- let lengthz' = length `map` (parse error)
我最初看到这个阅读this question 。我们有这个例子:
agreeLen :: (Eq a) => [a] -> [a] -> Int
agreeLen x y = length $ takeWhile id $ zipWith (==) x y
-- This may look like it can easily be made pointfree, however it cannot
-- agreeLen' :: (Eq a) => [a] -> [a] -> Int
-- agreeLen' = length $ takeWhile id $ zipWith (==) (zipWith is applied to too few arguments)
那么为什么我的第一个示例可以成为无点的,而其他两个则不能?
最佳答案
-- However this cannot: let lengthz x = length `map` x -- let lengthz' = length `map` (parse error)
\x -> length `map` x
写成自由点就是map length
。中缀反引号只是语法糖。 (正如切普纳指出的,如果你真的想要它,你可以使用一个部分,即 (length `map`)
。)
agreeLen :: (Eq a) => [a] -> [a] -> Int agreeLen x y = length $ takeWhile id $ zipWith (==) x y -- This may look like it can easily be made pointfree, however it cannot
这里的关键词是“容易”。如果你足够努力的话,几乎任何事情都可以成为免费的。在这种情况下,如果我们用 (.)
而不是 ($)< 来编写
:agreeLen
,则省略 y
参数很容易。/
agreeLen x y = (length . takeWhile id . zipWith (==) x) y
agreeLen x = length . takeWhile id . zipWith (==) x
对于x
,我们可以通过使用(.)
与zipWith (==) x
组成来处理它其他函数只是用函数修改值的另一种情况:
agreeLen x = (.) (length . takeWhile id) (zipWith (==) x)
agreeLen x = ((length . takeWhile id) .) (zipWith (==) x) -- cosmetical change
agreeLen x = (((length . takeWhile id) .) . zipWith (==)) x
agreeLen = ((length . takeWhile id) .) . zipWith (==)
这并不是您在实践中真正想要做的事情,但它肯定是可能的。
关于function - Haskell 中无点函数的先决条件是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40917772/