我必须写一个代码来创建一个函数,假设“ f”计算两个函数的总和,假设“ h”和“ g”。我是这样写的:
let h x = x + 2;;
let g x = x + 4;;
let f h x g x = h x + g x;;
但是,当我输入f h 2 g 4;;
时,它告诉我14错误,因为它应该显示12。为什么?
我还能以某种方式选择运行代码时要汇总哪些函数,还是需要每次都设置函数?
答案 0 :(得分:5)
您正在遮盖x
中的f
参数,因此f h 2 g 4
将得出h 4 + g 4
。您需要做的就是将其他参数之一命名为y
:
let f h x g y = h x + g y;;
答案 1 :(得分:1)
如果我们从数学意义上讲“两个函数的和”,那么我们应该让一个函数接受两个参数g
和h
,它们都是函数,并返回结果这也是一个函数(通常用g+h
表示,并且(g+h)(x) = g(x) + h(x)
这样)。
因此,目标是编写一个像这样的函数sum
:
let sum g h =
...
返回一个带有参数x
并返回f(x) + g(x)
的函数。
一个人可以这样:
let sum g h =
fun x -> (g x) + (h x)
您可以检查sum
的类型:
val sum : ('a -> int) -> ('a -> int) -> 'a -> int = <fun>
这意味着:
它接受('a -> int)
类型的第一个参数(该函数接受一个参数并返回一个整数:我们称为g的那个),
它还需要一个第二个参数,类型也为('a -> int)
(我们称为h),
它还涉及'a -> int
类型的函数,这也是我们想要的(因为g+h
实际上是一个带有参数并返回整数的函数。
在大多数编程语言中,您将不得不具有这种函数定义。在OCaml中,多亏了currying和一些黑魔法,您才可以说“但是,等一下,您决定对最后一个'a -> int
进行分组,并称返回类型为sum
,但是难道不是'a
是sum
的第三个参数,它的返回类型就是int
“?就像说我们可以将sum
“ functor”作为一个以g
和h
作为其参数并返回一个新函数的函数一样,该函数在调用{{ 1}},将返回x
,但我们可以等效地将其视为具有三个参数g(x)+h(x)
,g
和h
并返回x
的函数。这两个愿景在OCaml中是等效的。因此,我们可以使代码更简单,只需编写:
g(x)+h(x)
您可以验证其类型仍为
let sum g h x = (g x) + (h x)
符合预期。
从那里您可以享受语法乐趣,并为函数定义自己的sum运算符,例如val sum : ('a -> int) -> ('a -> int) -> 'a -> int = <fun>
:
++
然后在定义let (++) g h x = (g x) + (h x)
和g
之后使用它:
h
这将返回let g = ( ( + ) 5 )
and h = ( ( * ) 2 )
in
(g ++ h) 3
。