我在Haskell中有以下函数
agreeLen :: (Eq a) => [a] -> [a] -> Int
agreeLen x y = length $ takeWhile (\(a,b) -> a == b) (zip x y)
我正在努力学习如何编写“惯用的”Haskell,它似乎更喜欢使用.
和$
,而不是括号,并且在可能的情况下更喜欢无指针的代码。我似乎不能摆脱明确提到x
和y
。有什么想法吗?
我想我也会遇到同样的问题,去指向包含两个参数的任何函数。
顺便说一句,这只是为了写出好的代码;而不是一些“不惜一切代价让它变得无关紧要”的作业练习。
谢谢。
(添加评论)感谢您的回答。你让我相信这个函数不会从无指针中受益。你还给了我一些很好的例子来练习转换表达式。这对我来说仍然很困难,它们对Haskell来说似乎就像对C语言的指针一样重要。
发布于 2012-11-17 08:43:26
您还可以使用:
agreeLen :: (Eq a) => [a] -> [a] -> Int
agreeLen x y = length $ takeWhile id $ zipWith (==) x y
惯用的Haskell是更容易阅读的,而不一定是最无关紧要的。
发布于 2018-06-29 16:25:37
正如丹尼尔出色的回答所指出的,你的问题是当f
作为一个参数,g
作为两个参数时,组合f
和g
。这可以使用正确的运算符(以及类型签名(c -> d) -> (a -> b -> c) -> a -> b -> d
)编写为f ??? g
。这对应于(.).(.)
运算符(参见there),它有时被定义为.:
。在这种情况下,您的表达式将变为
length . takeWhile (uncurry (==)) .: zip
如果你习惯了.:
运算符,那么这个无点版本是完全可读的。我也可以改为使用(<$$$>) = fmap fmap fmap
和get
length . takeWhile (uncurry (==)) <$$$> zip
发布于 2018-06-29 14:39:05
另一种简明的、无指针的解决方案:
agreeLen = ((length . takeWhile id) .) . zipWith (==)
等同的:
agreeLen = (.) (length . takeWhile id) . zipWith (==)
https://stackoverflow.com/questions/13426417
复制相似问题