MIJ*_*THY 7 lambda haskell pointfree function-composition
我想了解如何以无点方式完成以下工作:
withinBounds :: [Int] -> Bool
withinBounds xs = (all (>= 0) xs) && (all (<= 8) xs)
Run Code Online (Sandbox Code Playgroud)
我明白,出于可读性/理智的考虑,以这种方式编写它是优越的,但我想更多地了解如何编写函数.我一直在摸索着如何做到这一点.整个(扩展?)类型签名是
[Int] -> ([Int] -> Bool) -> ([Int] -> Bool) -> (Bool -> Bool -> Bool) -> Bool
Run Code Online (Sandbox Code Playgroud)
我想要的组合的类型签名是
(a -> b) -> (a -> c) -> (b -> c -> d) -> (a -> d)
Run Code Online (Sandbox Code Playgroud)
我用以混蛋 - lambda形式的笔记写下了以下内容.如果有一种方法可以在某种程度上简化lambda演算的问题,那么如果可以解释它也会很棒:
\L@[] -> \f1@([] -> Bool) -> \f2@([] -> Bool) -> \f3@(Bool -> Bool -> Bool) -> f3.(f1.L).(f2.L)
Run Code Online (Sandbox Code Playgroud)
在上面,.是应用程序,@正在捕获(所以f3是(Bool - > Bool - > Bool)的另一个名称).非常感谢.
编辑:我知道这是不是最优化的或可重用的代码,我知道把这个变成自由点,使得它在可读性等的澄清方面糟糕的是,我问我怎么可以把它变成自由点,因为我想了解有关哈斯克尔和作曲的更多信息.
Edit2:关于无点的非常好的答案
你可以使用函数是Applicative的事实.并写withinBounds这样:
withinBounds = pure (&&) <*> all (>= 0) <*> all (<= 8)
Run Code Online (Sandbox Code Playgroud)
或者这样:
withinBounds = (&&) <$> all (>= 0) <*> all (<= 8)
Run Code Online (Sandbox Code Playgroud)
有一个类基本上专门用于无点组合†有多个"通道":Arrow.如果你决心让所有东西都没有点,那么这就是IMO的最佳选择.关于这一点的丑陋是你经常需要uncurry函数:
import Control.Arrow
withinBounds = all (>=0) &&& all (<=8) >>> uncurry (&&)
Run Code Online (Sandbox Code Playgroud)
如何使用图表最好地理解其工作原理:
all (>=0) ????
? ?
???? &&& >>> uncurry (&&) ???
? ?
all (<=8) ????
Run Code Online (Sandbox Code Playgroud)
† Arrow在广义环境中工作; 不仅适用于Hask功能,还适用于任何合适的类别.但它足以将其应用于函数.
围绕整个问题进行最终运行,我想我可能会这样写:
import Data.Ix
withinBounds = all (inRange (0, 8))
Run Code Online (Sandbox Code Playgroud)
当然,这有点冒险,因为那时人们自然会问如何inRange以无点的方式实现。如果你绝对不能使用inRange,那么我会这样内联实现它:
withinBounds = all (liftA2 (&&) (>=0) (<=8))
Run Code Online (Sandbox Code Playgroud)
这使用读者应用程序向两个函数提供单个参数。liftA2是您请求的组合函数,尽管参数已翻转:
requested :: (a -> b) -> (a -> c) -> (b -> c -> d) -> (a -> d)
liftA2 :: (b -> c -> d) -> (a -> b) -> (a -> c) -> (a -> d)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
337 次 |
| 最近记录: |