在Haskell中关于currying和点自由风格的混淆 [英] Confusion about currying and point free style in Haskell

查看:131
本文介绍了在Haskell中关于currying和点自由风格的混淆的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图实现这个功能:

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

这是这个问题。我试图在没有显式递归的情况下执行 。我想出了以下代码:

 每个f xs = liftM(全部id)$ sequence $ map f xs 

我的功能不起作用,因为它不是懒惰的(这在问题中是必需的),所以没有upvotes那里: - )。



然而,我并没有停留在那里。我试图使无点功能,以便它更短(甚至更酷)。由于参数 f xs 是表达式中最后一个,所以我放弃了它们:

  every = liftM(all id)$ sequence $ map 

但是这并没有像预期的那样工作,事实上它根本不起作用:

 
[1 1]编译主(stk.hs,解释)

stk.hs:53:42:
无法匹配预期的类型`[ma]'
与推断的类型'$($)'的第二个参数,即'map'
在'($)'的第二个参数中, ',即`sequence $ map'
在表达式中:liftM(all id)$ sequence $ map
失败,模块加载:无。

这是为什么?我的印象是可以简单地删除拖尾函数参数,这基本上就是currying的含义。

解决方案

$的定义是

  



$ b

让我们将函数完全加括号:

 每个f xs =(liftM(all id))(sequence((map f)xs))



和您的咖喱版本:

  every =( liftM(all id))(sequence map)

正如您注意到的,这些不一样。当它们是最后一个应用的时候,你只能删除尾随函数参数。例如,

  fx = gcx 

其实是

  fx =(gc)x 

,并且(gc)到x的应用最后一次,因此您可以写入

  f = gc 

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

  f $ g $ x 

相当于

 (f。g)$ x 

例如,

  every f xs = liftM(all id)$ sequence $ map f xs 

可以变成

 每个f xs =(liftM(全部id)。sequence。map f)xs 

此时您可以放弃xs:

 每f = liftM(全部id)。序列 。 map f 

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

  dot =((。)。(。))


$ b

有点数,这是

 (f`dot` g) x = f。 gx 

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

  every =(liftM(all id)。sequence)`dot` map 

不幸的是,由于Haskell类型系统的限制,这个需要一个明确的类型签名:

  every ::(Monad m)=> (a  - > m Bool) - > [a]  - > m Bool 


I was trying to implement the function

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

which was the topic for this question. I tried to do this without explicit recursion. I came up with the following code

every f xs = liftM (all id) $ sequence $ map f xs

My function didn't work since it wasn't lazy (which was required in the question), so no upvotes there :-).

However, I did not stop there. I tried to make the function point-free so that it would be shorter (and perhaps even cooler). Since the arguments f and xs are the last ones in the expression I just dropped them:

every = liftM (all id) $ sequence $ map 

But this did not work as expected, in fact it didn't work at all:

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

Why is that? I was under the impression that it was possible to simply drop trailing function arguments, which basically is what currying is about.

解决方案

The definition of $ is

f $ x = f x

Let's fully parenthesize your function:

every f xs = (liftM (all id)) (sequence ((map f) xs))

and your curried version:

every = (liftM (all id)) (sequence map)

As you noticed, these are not identical. You can only drop trailing function arguments when they are the last thing applied. For example,

f x = g c x

is actually

f x = (g c) x

and the application of (g c) to x comes last, so you can write

f = g c

One pattern with the application operator $ is that it often becomes the composition operator . in points-free versions. This is because

f $ g $ x

is equivalent to

(f . g) $ x

For example,

every f xs = liftM (all id) $ sequence $ map f xs

can become

every f xs = (liftM (all id) . sequence . map f) xs

at which point you can drop xs:

every f = liftM (all id) . sequence . map f

Eliminating the argument f is more difficult, because it is applied before the composition operator. Let's use the definition of dot from http://www.haskell.org/haskellwiki/Pointfree:

dot = ((.) . (.))

With points, this is

(f `dot` g) x = f . g x

and is exactly what we need to make every fully points-free:

every = (liftM (all id) . sequence) `dot` map

Sadly, due to restrictions in the Haskell type system, this one needs an explicit type signature:

every :: (Monad m) => (a -> m Bool) -> [a] -> m Bool

这篇关于在Haskell中关于currying和点自由风格的混淆的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆