我希望学习如何使用point-free方式完成以下操作:
withinBounds :: [Int] -> Bool
withinBounds xs = (all (>= 0) xs) && (all (<= 8) xs)
我知道为了易读性和代码的清晰度,这种写法更好,但我想学习如何组合函数。我一直在思考如何做到这一点。 整个(扩展?)类型签名是:
[Int] -> ([Int] -> Bool) -> ([Int] -> Bool) -> (Bool -> Bool -> Bool) -> Bool
我正在尝试实现的组合函数的类型签名是:
(a -> b) -> (a -> c) -> (b -> c -> d) -> (a -> d)
我用混合的lambda形式写了下面的笔记。如果有一种方法可以通过lambda演算来简化问题,那么请解释一下:
\L@[] -> \f1@([] -> Bool) -> \f2@([] -> Bool) -> \f3@(Bool -> Bool -> Bool) -> f3.(f1.L).(f2.L)
在上面的代码中,
.
表示应用程序,@
表示捕获(因此f3是(Bool -> Bool -> Bool)的另一个名称)。非常感谢。编辑:我知道这不是最优或可重用的代码,我知道将其转换为点自由会使其在可读性等方面变得更糟。澄清一下,我想知道如何将其转换为点自由,因为我想学习更多关于haskell和组合的知识。
编辑2:一个关于点自由的很好的SO答案。
withinBounds
函数无法组合使用,最好写一个单个元素的检查,然后在调用all
。实际上,我可能会直接将只能针对单个元素的withinBounds
函数嵌入到all withinBounds
中。 - Benjamin GruenbaumwithinBounds :: Ord e => (e, e) -> e -> Bool; withinBounds (a,b) x = a <= x && x <= b
。现在您的原始函数只是all (withinBounds (0,8))
。此外,我可以将其用作过滤器的谓词:filter (withinBounds (4,100)) [1..103]
。 - ZetawithinBounds (a,b) x = a <= x && x <= b
? - MIJOTHYuncurry ((. flip (<=)) . ap . ((&&) .) . (<=))
。最终,代码不仅要被计算机读取,还要被人阅读。无点版本不仅更长,而且比原始版本更难理解。 - Zetapointfree
包,在#haskell
的lambdabot上也可以找到,还有http://pointfree.io。话虽如此,我通常会移动参数直到最终得到可约化函数,例如:http://stackoverflow.com/a/36542287/1139697。 - Zeta