我试图实现该功能
every :: (a -> IO Bool) -> [a] -> IO Bool
这是 this question 的主题.我试图这样做 没有显式递归 .我想出了以下代码
every f xs = liftM (all id) $ sequence $ map f xs
我的功能不起作用,因为它不是懒惰的(这是问题中所要求的),所以那里没有投票:-)。
然而,我并没有就此止步。我试图使函数免积分这样它会更短(甚至可能更酷)。由于论点
f
和 xs
是我刚刚删除它们的表达式中的最后一个:every = liftM (all id) $ sequence $ map
但这并没有按预期工作,实际上它根本没有工作:
[1 of 1] 编译 Main(stk.hs,解释)
stk.hs:53:42:
无法匹配预期类型“[m a]”
针对推断类型 `(a1 -> b) -> [a1] -> [b]'
在`($)'的第二个参数中,即`map'
在`($)'的第二个参数中,即`sequence $map'
表达式中:liftM(all id)$sequence$map
失败,加载模块:无。
这是为什么?我的印象是可以简单地删除尾随函数参数,这基本上就是柯里化(Currying)的意义所在。
最佳答案
$的定义是
f $ x = f x
让我们把你的函数完全括起来:
every f xs = (liftM (all id)) (sequence ((map f) xs))
和你的 curry 版本:
every = (liftM (all id)) (sequence map)
正如您所注意到的,这些并不相同。您只能在最后应用尾随函数参数时删除它们。例如,
f x = g c x
实际上是
f x = (g c) x
并且 (g c) 对 x 的应用是最后的,所以你可以写
f = g c
应用程序运算符 $ 的一种模式是它经常成为组合运算符。无积分版本。这是因为
f $ g $ x
相当于
(f . g) $ x
例如,
every f xs = liftM (all id) $ sequence $ map f xs
可以变成
every f xs = (liftM (all id) . sequence . map f) xs
此时您可以删除 xs:
every f = liftM (all id) . sequence . map f
消除参数 f 更加困难,因为它是在组合运算符之前应用的。让我们使用 http://www.haskell.org/haskellwiki/Pointfree 中点的定义。 :
dot = ((.) . (.))
有了积分,这是
(f `dot` g) x = f . g x
并且正是我们需要使每一个完全免费的点:
every = (liftM (all id) . sequence) `dot` map
遗憾的是,由于 Haskell 类型系统的限制,这需要一个明确的类型签名:
every :: (Monad m) => (a -> m Bool) -> [a] -> m Bool
关于haskell - 对 Haskell 中的柯里化(Currying)和无点风格的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/907306/