Function 函数算术?

Function 函数算术?,function,functional-programming,Function,Functional Programming,整个夏天,我学习了一点PHP和javascript,所以我想今年我在数学方面也会领先一步,对我来说,这将是微积分。我在看一些视频时发现: 他说(f+g)(x)=f(x)+g(x)。我从未见过这样编写的函数,所以我想问一下这是否也是用编程语言实现的 假设我有,在伪代码中: function double(x){ return x*2; } function triple(x){ return x*3; } 是否有任何编程语言允许以下内容: (双+三)(10) …等于50 还有,有没有一个地方可

整个夏天,我学习了一点PHP和javascript,所以我想今年我在数学方面也会领先一步,对我来说,这将是微积分。我在看一些视频时发现:

他说
(f+g)(x)=f(x)+g(x)
。我从未见过这样编写的函数,所以我想问一下这是否也是用编程语言实现的

假设我有,在伪代码中:

function double(x){
return x*2;
}
function triple(x){
return x*3;
}
是否有任何编程语言允许以下内容:

(双+三)(10)

…等于50

还有,有没有一个地方可以让我从一个不到一万年的地方学习微积分


另外,我知道没有一种编程语言可以使用这种精确的语法,但我的意思是类似的…

大多数语言都允许您以这样或那样的方式执行此操作

function add(a, b) {
    return function(x) {
        return a(x) + b(x);
    };
}

add(double, triple)(10);  // Gives 50

您可以在Scala中轻松做到这一点:

abstract class F { f =>
  def apply(x: Double): Double
  def +(g: F) = { new F { def apply(x: Double) = f(x) + g(x) } }
}
object F {
  implicit def funcToF(f: Double => Double) = new F { def apply(x: Double) = f(x) }
}

import F.funcToF

val f = (x: Double) => 2*x
val g = (x: Double) => 3*x

val h = f + g
println(f(1))        // 2
println(g(1))        // 3
println(h(1))        // 5
println((f + g)(1))  // 5
您可以在

How to do上在线试用 在Haskell中,这实际上非常简单:

Prelude Control.Monad> liftM2 (+) (* 2) (* 3) 10
50
或者,或者:

Prelude Control.Applicative> (+) <$> (* 2) <*> (* 3) $ 10
50
这里发生了什么事?如果你在PHP和JavaScript方面有经验的话,Haskell是一种非常陌生的语言,所以我将尝试将其分解。但请注意:这里的相关函数(
liftM2
/
)比简单的使用要普遍得多,这可能会让您一开始很难理解它们。然而,由此产生的力量是值得的


高级别摘要 下面是我对一个非常高级的总结的尝试:
liftM2
接受一个二进制函数
op
,并生成一个对“更复杂”的值进行操作的二进制函数。如果“更复杂”的值是单参数函数
f
g
,那么只有一种很好的方法可以组合它们并生成一个新的单参数函数:生成一个将其参数
x
传递到
f
g
的函数,然后计算
fx`op`gx
——它使用
op
组合它们的结果。在JavaScript中,这类似于

function liftM2_functions(op) {
  return function (f,g) {
    return function (x) { op(f(x), g(x)) }
  }
}
由于
liftM2
仅适用于二进制函数,因此也有
liftM3
适用于三元函数,等等,但这很混乱;因此,引入了
操作符,使得
liftMn f a1 a2。。。a
完全等同于f a1 a2。。。一个


细节 如果你想得到更详细的答案,请继续阅读。我要警告你,我不知道这有多清楚;它依赖于一些我必须半手工保存的概念,我可能做得不好。但如果你是游戏玩家,我们开始吧

首先,让我们解释一些Haskell语法:

  • (*2)
    (*3)
    是书写
    \x->x*2
    \x->x*3
    的简捷方法,它们只是JavaScript
    函数(x){return x*2}
    函数(x){return x*3}
    的Haskell
  • (+)
    只是执行加法的函数;它是中缀运算符
    +
    的前缀形式
  • fx
    是函数应用程序
    f(x)
    fxy
    被解析为
    (fx)y
    ,但可以被视为双参数函数应用程序
    f(x,y)
  • $
    中缀运算符也是函数应用程序,但优先级较低:
    ..$x
    被解析为
    (…)x
  • 是奇特的中缀运算符
类型 所以!考虑到这一点,我们首先考虑第一个片段。在
liftM2(+)(*2)(*3)10
中,您想要的“函数添加函数”是
liftM2(+)
;它的两个参数是
(*2)
(*3)
;结果的参数是
10
。发生什么事?在Haskell中,正确的思考方式是从类型的角度来考虑。以下是相关类型,但请注意,您可能无法立即理解它们

liftM2 :: Monad m => (a -> b -> r) -> m a -> m b -> m r
(+)    :: Num a => a -> a -> a
(* 2)  :: Num a => a -> a
(* 3)  :: Num a => a -> a
10     :: Num a => a
这里,
f::t
表示“
f
具有类型
t
”。这些类型非常抽象,所以让我们简化一些事情。当您看到
numa
时,它的意思是“对于某个类型
a
,它是一个数字”;例如,我们可以将其视为
Int
Double
。所以这给了我们

(+)    :: Int -> Int -> Int
(* 2)  :: Int -> Int
(* 3)  :: Int -> Int
10     :: Int
好的,
10
是一个整数。那么
(*2)
(*3)
呢?这些函数由
->
表示,将整数映射为整数。您知道
(+)
是一个整数上的二进制函数,因此您可能会认为它的类型是
(Int,Int)->Int
。然而,在Haskell中,正确的方法是将其看作一个函数,它接受一个整数并返回另一个函数;这叫做咖喱。在JavaScript中,这将实现为

function add(x) {
  return function (y) {
    return x + y
  }
}
// Usage: add(10)(11) = 21.
你可能不明白为什么这是好的,但它将成为相关的一点

现在,让我们来处理
liftM2::Monad m=>(a->b->r)->ma->mb->mr
。这到底是怎么回事?忽略
Monad m
位,这表示
liftM2
采用一个双参数函数,一个“monadic
a
”和一个“monadic
b
”,并生成一个“monadic
r
”。不过,多亏了curry,这就等于说
liftM2
接受一个双参数函数并返回一个双参数函数,其参数和结果是一元的:
liftM2::Monad m=>(a->b->r)->(ma->mb->mr)
。这就是这里发生的:
liftM2(+)
是加法的一元版本

单子(不要惊慌!) 现在,我一直使用单子这个词,但我还没有定义它。我不打算!网上有很多monad教程,有些甚至不错;如果你好奇的话,去看看吧。现在你需要了解的是:一元值是一个以某种方式“增加”的值,通过有一些
function add(x) {
  return function (y) {
    return x + y
  }
}
// Usage: add(10)(11) = 21.
liftM2 :: (a -> b -> r) -> ((e -> a) -> (e -> b) -> (e -> r))
liftM2 (+) :: (e -> Int) -> (e -> Int) -> (e -> Int)
liftM2 f m1 m2 = do x1 <- m1
                    x2 <- m2
                    return $ f x1 x2
do doubled <- (* 2)
   tripled <- (* 3)
   return $ doubled + tripled
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
scala> import scalaz._
import scalaz._

scala> import Scalaz._
import Scalaz._

scala> val double = (x: Int) => 2 * x
double: (Int) => Int = <function1>

scala> val triple = (x: Int) => 3 * x
triple: (Int) => Int = <function1>

scala> val h = (double |@| triple) { _ + _ }
h: (Int) => Int = <function1>

scala> h(10)
res13: Int = 50