Jon*_*caC 25 haskell pointfree
我在Haskell中有以下功能
agreeLen :: (Eq a) => [a] -> [a] -> Int
agreeLen x y = length $ takeWhile (\(a,b) -> a == b) (zip x y)
Run Code Online (Sandbox Code Playgroud)
我正在努力学习如何编写'惯用'Haskell,它似乎更喜欢使用.而$不是括号,并且在可能的情况下更喜欢无点代码.我似乎无法摆脱提及x和y明确.有任何想法吗?
我认为我对点两个参数的任何函数都有同样的问题.
顺便说一下,这只是为了编写好的代码; 不是一些"使用任何必要的东西来使其无意义"的家庭作业.
谢谢.
(添加评论)感谢您的回答.你已经说服我这个功能不会从pointfree中受益.而且你也给了我一些很好的例子来练习转换表达式.这对我来说仍然很困难,而且它们似乎与Haskell一样重要,因为它指向C.
Dan*_*her 46
并且在可能的情况下更喜欢无点代码.
不是"在可能的地方",而是"它提高可读性(或具有其他明显优势)".
要点免费
agreeLen x y = length $ takeWhile (\(a,b) -> a == b) (zip x y)
Run Code Online (Sandbox Code Playgroud)
第一步是($)向右移动,用一个替换你拥有的那个(.):
agreeLen x y = length . takeWhile (\(a,b) -> a == b) $ zip x y
Run Code Online (Sandbox Code Playgroud)
现在,您可以更进一步地移动它:
agreeLen x y = length . takeWhile (uncurry (==)) . zip x $ y
Run Code Online (Sandbox Code Playgroud)
在那里你可以立即砍掉一个论点,
agreeLen x = length . takeWhile (uncurry (==)) . zip x
Run Code Online (Sandbox Code Playgroud)
然后你可以将其重写为合成运算符的前缀应用程序,
agreeLen x = (.) (length . takeWhile (uncurry (==))) (zip x)
Run Code Online (Sandbox Code Playgroud)
你可以写
f(gx)
如
f . g $ x
Run Code Online (Sandbox Code Playgroud)
一般来说,这里
f = (.) (length . takeWhile (uncurry (==)))
Run Code Online (Sandbox Code Playgroud)
并且g = zip,给
agreeLen x = ((.) (length . takeWhile (uncurry (==)))) . zip $ x
Run Code Online (Sandbox Code Playgroud)
从中可以x轻松删除参数.然后你可以将前缀应用程序(.)转换为一个部分并获取
agreeLen = ((length . takeWhile (uncurry (==))) .) . zip
Run Code Online (Sandbox Code Playgroud)
但是,这比原版的可读性差,所以除了练习将表达式转换为无点样式之外,我不建议这样做.
Gab*_*lez 12
你也可以使用:
agreeLen :: (Eq a) => [a] -> [a] -> Int
agreeLen x y = length $ takeWhile id $ zipWith (==) x y
Run Code Online (Sandbox Code Playgroud)
惯用的Haskell是更容易阅读的东西,不一定是最无点的东西.