hgi*_*sel 2 haskell function 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)
Run Code Online (Sandbox Code Playgroud)
我最初看到这个问题.我们有这个例子:
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)
Run Code Online (Sandbox Code Playgroud)
那么为什么我的第一个例子可以成为无点的,但另外两个不可以?
Run Code Online (Sandbox Code Playgroud)-- However this cannot: let lengthz x = length `map` x -- let lengthz' = length `map` (parse error)
\x -> length `map` x书面点免费简单map length.中缀反引号只是语法糖.(正如chepner所指出的,如果你真的想要它,你可以使用一个部分,即(length `map`).)
Run Code Online (Sandbox Code Playgroud)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
这里的关键词是"容易".如果你足够努力的话,几乎任何事情都可以毫无关键.在这种情况下,省略的y参数很容易,如果我们写agreeLen的方面(.),而不是($):
agreeLen x y = (length . takeWhile id . zipWith (==) x) y
agreeLen x = length . takeWhile id . zipWith (==) x
Run Code Online (Sandbox Code Playgroud)
至于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 (==)
Run Code Online (Sandbox Code Playgroud)
这不是你在实践中真正想做的事情,但它肯定是可能的.
您的第一个可以用无点样式编写,但您必须使其适合您map作为中缀函数的使用.
let lengthz = (length `map`) -- write the partial application as a section
Run Code Online (Sandbox Code Playgroud)
问题agreeLen在于zipWith它不是一个参数的函数,而是两个参数的函数.zipWith需要在将结果传递给它之前应用于两个参数takeWhile id.以无点样式编写它的不容易的方法是
-- via http://pointfree.io
agreeLen = ((length . takeWhile id) .) . zipWith (==)
Run Code Online (Sandbox Code Playgroud)
简单的讲,zipWith (==)适用于第一个参数x,以agreeLen产生一个新的功能(一个是获得一个列表,并返回一个压缩列表).这个新函数作为参数给出(length . takeWhile id) .,它产生一个新的组合函数,它接受第二个参数agreeLen并产生所需的Int值.
(@duplode可能派生这超过了我正要尝试干净.)
当初始函数需要超过2个参数时,一个快速失控的技巧是明确地解决它,进行组合,然后重新调整结果.
agreeLen = curry $ length . takeWhile id . (uncurry $ zipWith (==))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
576 次 |
| 最近记录: |