2

F#には、System.Linq.Expressionインスタンスを返す関数があります。

and System.Object with
  member this.ToExpression() = 
    match this with
    | :? System.Int32 -> Expression.Constant(this) :> Expression
    | :? System.Boolean -> Expression.Constant(this) :> Expression
    | :? Tml.Runtime.Seq as s -> s.ToExpression()
    | _ -> failwith "bad expression"

戻り値の型強制を省略すると、F#は関数の戻り型をConstantExpressionに推測します。私の最初の考えは、戻り型を#Expressionとして明示的にマークすることでしたが、それは機能しませんでした。リターン型を最も一般的な型に手動でキャストすることを伴わない、これを行うためのより洗練された方法はありますか?

ありがとう。

編集:答えてくれた皆さんに感謝します。明示的なリターンタイプ+アップキャストシナリオを使用します。

4

3 に答える 3

5

ここにあなたが好むかもしれないいくつかの方法があります:

open System.Linq.Expressions 

type System.Object with
    member this.ToExpression() : Expression =  // explicit
        match this with 
        | :? System.Int32 -> upcast Expression.Constant(this) // upcast
        | :? System.Boolean -> Expression.Constant(this) :> _ // _
        | _ -> failwith "bad expression"

宣言に戻り型を明示的に指定することで、たとえば「この型を推測してください」として、または制約からアップキャストする型を推測する演算子を使用しmemberて、本文でそれを推測できます。_upcast

于 2010-05-08T16:59:36.273 に答える
1

私は、これを無差別に書くためのこれほどエレガントな方法はないと思います。

コンパイラーは、match式のすべてのブランチが同じ戻り型を持つことを要求し、強制を暗黙的に挿入しません。キーワードを使用してupcast、ターゲットタイプを指定せずに強制を挿入できます。この場合、コンパイラは他の情報(タイプ注釈など)を使用してタイプを判別し、タイプを繰り返す必要はありません。

and System.Object with 
  member this.ToExpression() : Expression =  
    match this with 
    | :? System.Int32 -> upcast Expression.Constant(this) 
    | :? System.Boolean -> upcast Expression.Constant(this)
    | :? Tml.Runtime.Seq as s -> upcast s.ToExpression() 
    | _ -> failwith "bad expression" 

型アノテーションを追加upcastし、式と型アノテーションのそれぞれに追加したので、F#コンパイラはupcast結果をに強制する必要があると推測しますExpression。コンパイラが暗黙の強制を挿入する唯一の場所は関数を呼び出すときなので、次のように書くこともできます(ただし、それがより良いかどうかはわかりません)。

// Thanks to implicit coercions, we don't even need #type
let expr (a:Expression) = a

// and then for example:
| :? System.Int32 -> Expression.Constant(this) |> expr

何らかの理由で、upcastはキーワードであるため、パイプラインで使用することはできません。したがって、このような関数を定義すると、いくつかの利点があります。

于 2010-05-08T16:59:45.727 に答える
1

厳密に言えば、これは強制力を取り除くことではありませんが、私の意見では、見た目は少し良くなります(そして、タイピングも少し節約できます:))

open System.Linq.Expressions

let Constant obj = Expression.Constant(obj) :> Expression

type System.Object with
    member this.ToExpression()
        match this with 
        | :? System.Int32 -> Constant(this)
        | :? System.Boolean -> Constant(this)
        | _ -> failwith "bad expression"

定数のタイプは'->式であるため、どちらの場合でも機能します。欠点は、使用する式ファクトリメソッドごとに関数を定義する必要があることです。

于 2010-05-08T19:58:22.683 に答える