混乱关于扩充和点的自由风格在Haskell
题
我想要实现的功能
every :: (a -> IO Bool) -> [a] -> IO Bool
这是主题 这个问题.我试图做这个 没有明确的递归.我想出了下列代码
every f xs = liftM (all id) $ sequence $ map f xs
我的功能没有运作,因为它不是懒惰的(这是需要在该问题),所以没有"顶"有:-).
然而,我并没有停止。我试图让的功能 点免费的 因此,它将更短(甚至冷却机)。由于参数 f
和 xs
是最后表达我刚把他们:
every = liftM (all id) $ sequence $ map
但是,这并没有预期的工作,事实上它并没有在所有的工作:
[1 of 1] Compiling Main ( stk.hs, interpreted ) stk.hs:53:42: Couldn't match expected type `[m a]' against inferred type `(a1 -> b) -> [a1] -> [b]' In the second argument of `($)', namely `map' In the second argument of `($)', namely `sequence $ map' In the expression: liftM (all id) $ sequence $ map Failed, modules loaded: none.
为什么?我的印象是,它是可以简单地拖追踪功能的参数,这基本上是什么样的扩充。
解决方案
的$定义是
f $ x = f x
让我们充分圆括号你的函数:
every f xs = (liftM (all id)) (sequence ((map f) xs))
和您的咖喱版本:
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
不隶属于 StackOverflow