3

今日、F# を少しいじって、次のように書きました。

let sq x = x * x

let i = sq 3
let d = sq 3.0

3 行目または 4 行目のいずれかを削除するとコンパイルされますが、両方が存在する場合はコンパイルされません。

エラーが発生しますThis expression should have type 'int', but has type 'float'

4

5 に答える 5

6

型推論は、関数sqが typeint -> intを持つように機能します。これは、コンパイラがその関数の使用を初めて確認したときに、整数を渡すためです。sqしたがって、これは整数を受け取る関数であると想定され、関数 ( x * x) の定義により、整数も返されます。

F# で完全に汎用的な算術関数を定義するのは少し複雑ですが、それを行う 1 つの方法は、関数inlineを次のように作成することです。

let inline sq x = x * x

このようにして、関数の本体は呼び出しサイトで毎回インライン化されるため、インライン化sqされた関数を使用することは、使用されるたびに本体を置き換えることと同じになります。

このアプローチには欠点があり、この質問を見るのは興味深いと思います。

于 2013-07-20T13:34:45.510 に答える
2

他の答えは正しいですが、ジグソーパズルの重要な部分を省略しています: F# では、int と float の間などの暗黙的な変換がないという事実です。これが、2 番目の呼び出しが実際に、実在しない別のオーバーロードを float 引数で呼び出している理由です。

于 2013-07-20T15:21:14.167 に答える
2

Let バインド関数はオーバーロードできません。特定のケースではinline、コンパイル時に関数本体をインライン化するため、適切な実装を選択できる を*使用できます。

let inline sq x = x * x
于 2013-07-20T13:34:09.867 に答える
1

let sq x = x * xデフォルトの関数のタイプはint -> intです。

これを a のコンテキストに置くとlet d = sq 3.0、F# コンパイラはその型を として推論しfloat -> floatます。

いずれにせよ、この関数はint->int、 またはのいずれかの型シグネチャを 1 つだけ持つことができますfloat->float

于 2013-07-20T13:23:52.840 に答える
1

これは、バインディングの実装方法の制限です。2 つの選択肢があります。

まず、宣言にインラインを追加します。

次に、クラスでメンバー バインディングを使用し、さまざまな型をオーバーライドします。

于 2013-07-20T13:33:51.840 に答える