问题描述
假设在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 asGrouping functions in Haskellbut 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.
偶然地,部分应用的函数是 Monad实例.这意味着您可以:
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
是已应用隐式par
的f
.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中部分应用几个功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!