haskell - 对 Haskell 中的柯里化(Currying)和无点风格的困惑

标签 haskell currying pointfree

我试图实现该功能

every :: (a -> IO Bool) -> [a] -> IO Bool 

这是 this question 的主题.我试图这样做 没有显式递归 .我想出了以下代码
every f xs = liftM (all id) $ sequence $ map f xs

我的功能不起作用,因为它不是懒惰的(这是问题中所要求的),所以那里没有投票:-)。

然而,我并没有就此止步。我试图使函数免积分这样它会更短(甚至可能更酷)。由于论点fxs是我刚刚删除它们的表达式中的最后一个:
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/

相关文章:

javascript - 'currying' 和 'composition' 在 Javascript 中是同一个概念吗?

javascript - 为什么映射到 `parseInt` 无点样式不能按预期工作?

javascript - 条件函数的无点样式

haskell - Haskell 有类似 Incanter 的东西吗?

Haskell:了解部分应用程序吗?

swift - 为什么柯里化(Currying)函数需要外部参数名称?

Ruby 传递方法

haskell - 其他表达式中的“where”

haskell - 对酿造操作序列进行建模

haskell - 的用法!在 Haskell 类型中