在Haskell中部分应用几个功能 [英] Partially apply several functions in Haskell

查看:92
本文介绍了在Haskell中部分应用几个功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设在Haskell中,我有一堆函数都依赖于相同的参数类型:

Suppose, in Haskell, I have a bunch of functions that all depend on the same parameter type:

f :: Par -> a -> b
g :: Par -> b -> c

当我编写更多仍取决于此参数类型的函数时,我可以做类似的事情

As I'm writing more of these functions that still depend on this parameter type, I can do something like

h :: Par -> a -> c
h par = myg . myf
    where myf = f par
          myg = g par

但是我仍然必须写这些where行.问题是:可以避免吗?

However I keep having to write these where lines. The question is: can this be avoided?

[我试图提供一个最小的例子来说明问题,但是显然这个例子太少了,无法说明我想要的东西.在实际问题中,h当然不仅仅是f和g的组成.所以这是一些实际的代码:

[ I tried to provide a minimal example to illustrate the problem but apparently the example is too minimal to illustrate what I want. In the actual problem h is of course not just the composition of f and g. So here is some actual code:

有功能

apply :: ChamberLattice -> ChLatword -> ChLatWord
reduce :: ChamberLattice -> ChLatWord -> ChLatWord

我正在定义一个函数

chaseTurn :: ChamberLattice -> Turn -> Parity -> ChLatWord -> ChLatWord
chaseTurn cl Straight _ xs = xs
chaseTurn cl t parity xs = if ((turn parity xs) == t)
                           then case myApply xs of
                               (y1:y2:ys) -> (y1:y2:(myChaseTurn t parity ys))
                               ys -> ys
                           else myReduce xs
where myApply = apply cl
      myChaseTurn = chaseTurn cl
      myReduce = reduce cl

]

(此问题与 Haskell中的分组功能 但是我在那儿用了一些不幸的词,使人分心.)

(This question is essentially the same as Grouping functions in Haskell but there I used some unfortunate words that distracted people.)

推荐答案

您正在做很多h par = f par . g par,而par的内容开始变得混乱.

You're doing h par = f par . g par a lot, and the par stuff starts to clutter.

您不能执行h = f . g,因为必须同时传递par参数.

You can't do h = f . g, since the par argument must be passed along, too.

因此,您想出了一个功能强大的合成运算符,可以为您完成此操作:

So you come up with a high-powered composition operator that will do this for you:

-- (.) :: (b -> c) -> (a -> b) -> a -> c
(§) :: (par -> b -> c) -> (par -> a -> b) -> par -> a -> c
(§) f g par = f par . g par

现在您可以执行h = f § g.该运算符可能是以前发明的.

Now you can do h = f § g. This operator was probably invented before.

偶然地,部分应用的函数是

Incidentally, partially applied functions are instances of Monad. This means you can do:

(§) f g par = (do { fpar <- f; gpar <- g; return (fpar . gpar) }) par

或者只是:

(§) f g = do { fpar <- f; gpar <- g; return (fpar . gpar) }

(此处,fpar是已应用隐式parf.monad实例使par隐式.)

(Here, fpar is f to which an implicit par has been applied. The monad instance makes par implicit.)

如果要参数化此do-block:

If we were to parameterize this do-block:

(§) f g = ( \f m1 m2 -> do { x1 <- m1; x2 <- m2; return (f x1 x2) } ) (.) f g

然后eta减少参数:

(§) = ( \f m1 m2 -> do { x1 <- m1; x2 <- m2; return (f x1 x2) } ) (.)

在Hoogle上查找类似于此do-block的内容,您会发现liftM2:

And look on Hoogle for something that looks like this do-block, you'd find liftM2:

(§) = liftM2 (.)

这时我们真的不需要给它起一个特殊的名称,因为liftM2 (.)已经很短了.

At which point we don't really need to give it a special name, since liftM2 (.) is already pretty short.

这篇关于在Haskell中部分应用几个功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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