2013-05-19 9 views
17

簡単な質問です。標準ライブラリ(またはJane StreetのCoreまたはBatteries)で定義されているOCamlに中置関数合成演算子があるかどうか疑問に思っています.Haskellの(。)関数のように、たくさんのかっこを保存しています。(f . g . h) xあまり魅力的ではないf (g (h x)))OCamlに中置関数合成演算子がありますか?

ありがとうございました。

答えて

18

答えはflip :-)と同じです。関数の構成はOCaml標準ライブラリでは定義されていません。この場合、それは私が一度逃したものではなく、いつもそれを逃しています。

OCaml Batteries Includedプロジェクトでは、BatStdモジュールの演算子-|を使用して(与えられた順序で)関数の構成を定義します。 lukstafiが指摘しているように(下記参照)、このオペレータはバッテリの将来のリリースで明らかに%に変更されます。 (私はソースツリーでこれを確認しました)

私が見る限り、Jane Street Coreプロジェクトは関数合成演算子を定義していません。これは、Fnモジュールに関数composeを定義します。

+1

感謝あなたはジェフリーです。あなたはとても助けてくれました。私はまた、現時点で彼らのドキュメンテーションにアクセスできない。 あなたの情報に従って、私はとにかくJane StreetのCore.Std.Fn(cf https://github.com/janestreet/core/blob/master/lib/fn)のソースファイルに 'compose'関数を発見しました。 mli、31行目)。 ありがとうございます。 – tfboy

+0

FYIこれは伝統的なドキュメントリンクですが、ダウンしています:https://ocaml.janestreet.com/ocaml-core/latest/doc/ – rgrinberg

+0

(ありがとうございます。代わりに新しいリンクがあります) –

9

コアにはFn.composeの機能がありますが、埋め込み演算子ではありません。また、通常の関数として実装され、実行時オーバーヘッドを持ちます。

実際には、パイプ演算子を使用するとかなり便利です。コンパイラで直接実行されるようなランタイムオーバーヘッドはありません(4.00以降)。詳細は、Optimized Pipe Operatorsを参照してください。

パイプ演算子はコアで '|>'として使用できます。それで、あなたは次のようにあなたの式を書き換えることができます。型シグネチャを持つ

let (<<) f g x = f(g(x));; 

h x |> g |> f

+2

コアのシングルパイプ演算子 '|>'は、覚えておく必要のある中置演算子の数を簡単にするため、良い選択であると考える人もいます。理論的には、関数合成とパイプ演算子をそれぞれ順方向と逆方向に持つことができますので、合計4つです。しかし、それは本当に助けになるのですか?いくつかの人はそれを過度のものとみなし、単に '|>'を持つ方が好きです。 –

6

私はF#でそれは単にとして定義されています、オペレータは含めてかなり容易であることを追加したいval (<<) : f:('a -> 'b) -> g:('c -> 'a) -> x:'c -> 'b ...あなたが必要な正確に何

(f << g << h) x = f(g(h(x)) 

をやってあなたは私が好きな

に持っていない場合ので、あなたは、電池プロジェクトを必要としません

let (>>) f g x = g(f(x));; 

(f >> g >> h) x = h(g(f(x)) 
+0

それは素晴らしいです。 OCamlでは、 '>>'演算子は完全に動作します。しかし、 '<<"演算子はインタプリタを完全にハングします。なぜあなたはこれがだと思いますか? –

+1

私は上記の両方の定義をテストしましたが、あなたの主張の証拠はありません。良い答えが必要な場合は、いくつかのサンプルコードで完全な質問を投稿する必要があります。 –

+1

トークン受け入れエラーのようです。私は上記のように演算子を定義し、 'let f =(+)1'と' let g =(*)3'を定義しました。 REPLでは、「(f >> g)10」は「33」です。しかし、 '' f 'g)10''は、' '' 'トークンが悪いので、通訳者が入力を処理することはできません(以前はREPLが掛かっていたと思っていましたが、コンパイルしようとしたときそれはファイルからのものです)。これは '<<'が予約されたキーワード(http://caml.inria.fr/pub/docs/manual-ocaml/lex.html#sec72)であるかもしれませんが、何らかの理由で '>>'が動作します今のところ)。私はOCaml 4.01.0を実行しています。 –

4

中置組成オペレータの使用は落胆しているように見える:ご想像の通り>>オペレータが反対をしているので、それは<<のように見える理由があることを追加します。 (this discussion参照)。

f (g (h x)))の代わりにf @@ g @@ h xと書くことができます。

0

多分それがあなたを助けるかもしれません。

let identite f = f 
let (>>) = List.fold_right identite 

試験:Containers

# let f=fun x-> x+1 and 
     g=fun x-> x*2 and 
     h=fun x-> x+3;; 

# [f;g;h] >> 2;; 
- : int = 11 
1

(まだOCamlのための別のSTDLIB置換)、関数合成演算子は%と呼ばれ、​​モジュールに見出すことができる:

open Containers 
open Fun 

let is_zero n = (n = 0) 

let nonzeros = List.filter (not % is_zero) [0;1;2;3;0] 
関連する問題