関数型言語、特に Ocaml で複合関数を定義するにはどうすればよいですか? たとえば、別の関数の結果の否定を計算する関数を作成した場合、つまり次のようになります。 not(f(x))
wheref(x)
はブール値を返します。どうすれば定義できますか?
3 に答える
f
次のタイプのfunction が与えられます。
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 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
編集:ああ、私はチャックが実際にこれをしたと思います。私はたぶんスキミングするべきではなかったでしょう。いずれにせよ、たまたま作成機能を折りたたむのが好きなので、これからも続けていきます。:p
あなたがここでどこまで行こうとしているのか正確にはわかりません — あなたが書いたコードは問題なく動作します。そのため、このようなものをゼロから作成する方法について、簡単なステップバイステップで説明します。単純な否定は次のとおりです。
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