2

この非常に特定の状況を修正する方法を探しています:toF関数パラメーターを取り、gそれに基づいて結果の関数を作成する関数ファクトリーがあります。f

let toF g = 
    let f x = g x
    f
let f = toF id

問題は、私が得ることです

error FS0030: Value restriction. The value 'f' has been inferred to have generic type    val f : ('_a -> '_a)    Either make the arguments to 'f' explicit or, if you do not intend for it to be generic, add a type annotation.

型注釈を追加することもできます (これはあまりやりたくありません)。代わりに、次のように書き直すこともできます。

let f' g x = g x
let f x = f' id x

このようにするのは好きではありません。そうすると、呼び出すたびに途中fで別の呼び出しを行うf'ことになるからgです。最初の例はgクロージャーを保持し、1 回の呼び出しのみを必要とします。

更新(トーマス用)

私はあなたが提案したことを試しました。

let toF g = 
    printfn "Creating f using g"
    let f x =
        printfn "x: %A" x
        g x
    f
let f x = toF id x

let ``test``() =
    1 |> f |> f |> ignore

基本的に何が起こっているかというと、関数を呼び出すたびに、f最初toF idに構成された関数の取得が呼び出され、次にその構成された関数が呼び出されますx

Creating f using g
x: 1
Creating f using g
x: 1

fしたがって、基本的に、構成はへの後続の呼び出しを介して への呼び出しごとに作成されますtoF。しかし、これはまさに私が避けようとしていたことです。定義することlet f = toF idで、私は 1 回閉じてすぐに呼び出せるようにしたいと考えていました。したがって、私が期待している出力は次のようになります。

Creating f using g
x: 1
x: 1

更新 2

以下は、まったく同じ理由で機能しません。

let toF g = 
    printfn "Creating f using g"
    let f x =
        printfn "x: %A" x
        g x
    f
let f() = toF id
let fg = f()
4

2 に答える 2

7

f構文関数を作成するだけです。

let toF g = 
    let f x = g x
    f
let f x = toF id x

f構文的に関数 (パラメーターを受け取る) ではなく値の場合、「値の制限」エラーが発生します。ここで説明するつもりはありません。なぜなら、「F# 値制限エラーについて」などの以前の投稿に既に優れた情報があるからです。

編集- 一度だけ呼び出されることを確認したい場合g(ただし、コードを汎用にしたい場合)、最も簡単な方法は、未使用unitのパラメーターを追加して (関数にするため)、それを一度呼び出すことです (これにより、汎用パラメーターが決定されます)。 ) 結果を複数回使用します。

let toF g = 
    let f x = g x
    f
let f () = toF id

let fg = f ()
fg 1
fg 2

悲しいことに、これは必要です。なぜなら、ジェネリックであるが何らかの計算によって返される関数を持つと、実際には型システムに微妙な穴ができるためです。これが「値の制限」の理由です。

于 2013-10-24T17:35:35.817 に答える