部分评估Haskell中的几个函数 [英] Partially evaluate several functions in Haskell

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

问题描述

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

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

由于我正在编写更多仍然依赖于此参数类型的函数,因此我可以就像

  h :: Par  - > a  - > c 
h par = myg。 myf
其中myf = f par
myg = g par par

但是我保留必须写这些其中行。问题是:这可以避免吗?



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

有函数

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

我正在定义一个函数

  chaseTurn :: ChamberLattice  - >转 - >奇偶校验 - > ChLatWord  - > ChLatWord 
chaseTurn cl Straight _ xs = xs
chaseTurn cl t奇偶校验xs = if((turn parity xs)== t)
then case myApply xs
(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中对函数进行分组
但在那里我使用了一些让人分心的不幸词语。)

f 和 g

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

函数也是类型,所以我们可以任意决定别名 a - > b φ phi 而不是 f )和 b - > c γ gamma 而不是 g )。 (是的,当你的信件用完时,你可以使用希腊字母!)

这意味着你可以将你的函数视为具有类型

  f :: Par  - > φ
g :: Par - > γ

这些都是所谓的 reader monad 的自动实例,这也是一个(应用)函数。特别是( - >)Par ,或者,如果有帮助, Par - > Applicative 实例。这意味着您可以使用纯粹<>



作为第一次尝试,您可以写一些类似于

  pure(\xy  - >( x,y))* f * g 

为了简单理解该构图如何工作。该表达式的类型为 Par - > (φ,γ),可以这么说。 lambda表达式只需从 f '容器'中取 x ,并且 y g '容器'的c $ c>,并将它们组合到一个元组中。元组的第一个元素的类型为φ,第二个元素的类型为γ



插入φγ的定义,就会得到类型参数 - > (a - > b,b - > c)



而不是返回值作为函数的元组,组成这些功能。您可以使用函数组合运算符作为:

  h =纯的(\ xy  - > x。y)* f * g 

然而,显式lambda表达式可以被eta简化为:

  h =纯(。)* * f * g 

最后,不要写 pure(。)*< 您可以使用中缀< $> 运算符:

  h =(。)< $> f * g 

这个函数的类型是 Par - > a - > c


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

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

[Edit: 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:

There are functions

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

and I am defining a function

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

]

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

解决方案

In Haskell, all functions take one input argument. Sometimes, though, the return value of applying a function is a new function. As a first step, then, you can make that more explicit by putting brackets around the return value of your functions f and g:

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

Functions are types as well, so we could arbitrarily decide to alias a -> b to φ (phi instead of f) and b -> c to γ (gamma instead of g). (Yes, when you run out of letters, you reach for the Greek alphabet!)

This means that you can view your functions as having the types

f :: Par -> φ
g :: Par -> γ

These are both automatically instances of the so-called reader monad, which is also an (applicative) functor. Particularly, (->) Par, or, if it helps, Par -> is an Applicative instance. This means that you can use pure and <*> with it.

As a first attempt, you can write something like

pure (\x y -> (x, y)) <*> f <*> g

in order to simply understand how that composition works. That expression has the type Par -> (φ, γ), so to speak. That lambda expression simply takes x from the f 'container', and y from the g 'container', and combines them in a tuple. The first element of the tuple has the type φ, and the second element has the type γ.

Plugging in the definitions of φ and γ, you get the type Par -> (a -> b, b -> c).

Instead of a return value as a tuple of functions, you want to compose these functions. You can use the function composition operator . for that:

h = pure (\x y -> x . y) <*> f <*> g

That explicit lambda expression, though, can be eta-reduced to:

h = pure (.) <*> f <*> g

Finally, instead of writing pure (.) <*> you can use the infix <$> operator:

h = (.) <$> f <*> g

This function has the type Par -> a -> c.

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

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