如何在函数式语言中定义复合函数,特别是使用Ocaml?例如,如果我编写一个计算另一个函数结果否定的函数,那就是:not(f(x))
其中f(x)
返回一个布尔值。我该如何定义它?
答案 0 :(得分:12)
给定一些函数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
答案 1 :(得分:5)
我不确定你到底要走多远 - 你写的代码会正常工作。因此,我将逐步介绍如何从头开始编写这些内容。简单的否定只是:
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
答案 2 :(得分:3)
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
的类型为int -> int
,其有效定义为:
let composite_function n =
let n2 = (n + 1) * 2 in
n2 * n2
编辑:哦,我猜Chuck实际上是这么做的。我可能不应该只是撇去。在任何情况下,我碰巧喜欢折叠撰写函数,所以我会保持这一点。 :P