如何用函数式语言定义复合函数,尤其是使用 Ocaml?例如,如果我编写一个函数来计算另一个函数的结果的否定,即:not(f(x))
wheref(x)
返回一个布尔值。我该如何定义它?
3 回答
给定一些 function f
,它具有以下类型:
f: 'a -> bool
您希望能够生成另一个函数来包装它以否定结果。让我们考虑一下这个新函数的类型,我们称之为negated
(我没有使用not
,因为它是内置函数的名称):
negated: ('a -> bool) -> 'a -> bool
为什么是这种类型?为什么不'a -> bool
呢?请记住,我们希望这个新函数接收现有函数并返回一个具有相同类型但执行不同操作的新函数。为了看得更清楚,你可以这样想:('a -> bool) -> ('a -> bool)
这是等价的。
那么现在有了这些约束,我们该如何编写negated
函数呢?
let negated f = ??
那么我们首先要考虑这个函数需要返回一个函数:
let negated f = (fun x -> ??)
接下来是什么?好吧,我们知道我们创建的新函数应该使用参数调用我们的包装函数并将其取反。让我们这样做,使用参数调用函数:f x
,并否定它:not (f x)
。这给了我们最终的函数定义:
let negated f = (fun x -> not (f x))
让我们看看它的实际效果:
# let f x = x < 5;;
val f : int -> bool = <fun>
# f 2;;
- : bool = true
# f 8;;
- : bool = false
# let negated f = (fun x -> not (f x));;
val negated : ('a -> bool) -> 'a -> bool = <fun>
# let g = negated(f);;
val g : int -> bool = <fun>
# g 2;;
- : bool = false
# g 8;;
- : bool = true
我不确定你到底想在这里走多远——你写的代码可以正常工作。因此,我将逐步介绍如何从头开始编写这些内容。简单的否定就是:
let not = function
| true -> false
| false -> true
你可以怎么写not (f x)
,它会给你结果的否定f x
。
对于组合函数的函数,您可以使用:
let comp f g x = f (g x)
那么我们可以这样做:
let even n = match n mod 2 with
| 0 -> true
| _ -> false
let odd = comp not even
哇,所有这些过于复杂的答案是怎么回事?有什么问题:
let compose f g x = g (f x)
要得到你的g(x) = not(f(x))
,假设你有一个f : 'a -> bool
:
let g = compose not f
此外,您可以做一些很酷的事情,例如:
let composite_function =
let id x = x in
let transforms = [
(fun n -> n + 1);
(fun n -> n * 2);
(fun n -> n * n)
] in
List.fold_left compose id transforms
现在composite_function
has type int -> int
,它的有效定义是:
let composite_function n =
let n2 = (n + 1) * 2 in
n2 * n2
编辑:哦,我猜查克确实这样做了。我可能不应该只是略读。无论如何,我碰巧喜欢折叠 compose 功能,所以我会继续这样做。:p