关于Haskell中的currying和point自由风格的困惑

Jon*_*nas 9 haskell currying pointfree

我试图实现这个功能

every :: (a -> IO Bool) -> [a] -> IO Bool 
Run Code Online (Sandbox Code Playgroud)

这是这个问题的主题.我没有明确的递归尝试这样做.我想出了以下代码

every f xs = liftM (all id) $ sequence $ map f xs
Run Code Online (Sandbox Code Playgroud)

我的功能不起作用,因为它不是懒惰的(问题中需要),所以没有赞成在那里:-).

但是,我并没有就此止步.我试图使功能无点,以便它更短(甚至更冷).由于参数fxs在我刚把他们表达了最后的:

every = liftM (all id) $ sequence $ map 
Run Code Online (Sandbox Code Playgroud)

但是这没有按预期工作,事实上它根本不起作用:

    [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.

这是为什么?我的印象是,可以简单地删除尾随函数参数,这基本上就是currying的内容.

Dav*_*ave 25

$的定义是

f $ x = f x
Run Code Online (Sandbox Code Playgroud)

让我们完全括起你的功能:

every f xs = (liftM (all id)) (sequence ((map f) xs))
Run Code Online (Sandbox Code Playgroud)

和你的咖喱版:

every = (liftM (all id)) (sequence map)
Run Code Online (Sandbox Code Playgroud)

正如您所注意到的,这些并不完全相同.只有在应用的最后一个事物时才能删除尾随函数参数.例如,

f x = g c x
Run Code Online (Sandbox Code Playgroud)

实际上是

f x = (g c) x
Run Code Online (Sandbox Code Playgroud)

并且(gc)对x的应用是最后的,所以你可以写

f = g c
Run Code Online (Sandbox Code Playgroud)

应用程序运算符$的一种模式是它经常成为组合运算符.在免费版本中.这是因为

f $ g $ x
Run Code Online (Sandbox Code Playgroud)

相当于

(f . g) $ x
Run Code Online (Sandbox Code Playgroud)

例如,

every f xs = liftM (all id) $ sequence $ map f xs
Run Code Online (Sandbox Code Playgroud)

可以变成

every f xs = (liftM (all id) . sequence . map f) xs
Run Code Online (Sandbox Code Playgroud)

此时你可以删除xs:

every f = liftM (all id) . sequence . map f
Run Code Online (Sandbox Code Playgroud)

消除参数f更加困难,因为它在合成运算符之前应用.让我们使用http://www.haskell.org/haskellwiki/Pointfree中点的定义:

dot = ((.) . (.))
Run Code Online (Sandbox Code Playgroud)

有点,这是

(f `dot` g) x = f . g x
Run Code Online (Sandbox Code Playgroud)

而且正是我们需要让每一个完全无点的:

every = (liftM (all id) . sequence) `dot` map
Run Code Online (Sandbox Code Playgroud)

遗憾的是,由于Haskell类型系统的限制,这个需要一个显式类型签名:

every :: (Monad m) => (a -> m Bool) -> [a] -> m Bool
Run Code Online (Sandbox Code Playgroud)

  • 或者您可以使用-XNoMonomorphismRestriction并删除显式类型sig. (2认同)