理解嵌套函数逻辑的更好方法(Currying)

时间:2012-12-03 12:14:35

标签: functional-programming ocaml

我正在学习Jason Hickey's Introduction to Objective Caml。只是对嵌套函数(currying)提出疑问。

现有问题How to understand the "Currying" in Haskell?,但我想我正在寻找稍微不同的问题的答案。


它表示我们可以将let sum = fun i j -> i + j;;写为let sum = fun i -> fun j -> i + j;;

我的问题很简单:

我能否以这种方式理解上述定义:let sum = fun i -> i + fun j -> j;;

我知道它不会通过编译器,但我只是尝试将这种OCaml function definition映射到mathematics functions

在我的想象中,我们可以在数学中轻松地编写函数f(i) = i + g(j); and g(j) = j

我是否应该总是进行这种逻辑映射以便于理解?

2 个答案:

答案 0 :(得分:3)

你的想象力并不正确:f(i) = i + g(j)并不意味着j在这里未定义。

理解fun i j -> foo的正确方法是将其视为更明确的符号fun i -> fun j -> foo的一些方便的语法糖。

以下所有定义完全相同:

let sum i j = i + j
let sum i = fun j -> i + j
let sum = fun i -> (fun j -> i + j)
let sum = fun i -> fun j -> i + j
let sum = fun i j -> i + j

let sum i =
  let add_i = fun j -> i + j in
  add_i

在数学上这可以写成(i↦(j↦i + j)),作为...的元素 功能空间(ℕ→(ℕ→ℕ))。

答案 1 :(得分:1)

OCaml函数可以直接映射到数学符号和从数学符号映射。但是,您需要意识到数学符号是模糊的。函数值f(i)与特定值i和函数f本身之间没有明确的区别。当一个人意味着函数f(i)本身时,通常会写f。 (“让我们考虑函数f(i)= i + 1 ...此函数是......”)要在OCaml中编写正确的代码,您必须清楚地看到您是使用函数本身还是使用值功能。

当您用数学符号说“考虑函数f(i,j)=i+g(j) where g(j)=j时,您正在编写函数的值。在OCaml中,这被转换为

  let f i j = 
       let g j = j in 
       i + g j;;

  let f = 
     let g = fun j -> j 
     in
     fun i j -> i + g j;;

如果您正在尝试编写let sum = fun i -> i + fun j -> j;;,那么在数学符号中您会说“考虑函数sum,使sum(i) = i + g,其中g是由{{1}定义的函数}“。这在数学上是不正确的:您无法添加整数值 g(j)=j函数 i。您只能在某个其他整数g上添加函数i的整数g。严格来说,表达“j”是不确定的。您要么写i+g,要么i + g(i),而不是i+g(j)。这在数学中是如此,在OCaml中也是如此。