F#TupleでCustomComparisonおよびCustomeCulationとのカスタム比較の実装
-
29-09-2019 - |
質問
私は特定のトピックを尋ねるためにここにいます - 私は本当にウェブ上でこれに関する情報をほとんど見つけませんでした。 MinimaxアルゴリズムのF#バージョンを実装しています。私が今抱えている問題は、私の木の葉を比較したいということです(以下のデータ構造)。 VSが私に与えたエロを検索すると、私はこのようなものに到着しました:
私が持っていたツリータイプ:
type TreeOfPosition =
| LeafP of Position
| BranchP of Position * TreeOfPosition list
icomparableを実装する誘惑者
type staticValue = int
[<CustomEquality;CustomComparison>]
type TreeOfPosition =
| LeafP of Position * staticValue
| BranchP of Position * TreeOfPosition list
override x.Equals(yobj) =
match yobj with
| :? TreeOfPosition as y -> (x = y)
| _ -> false
override x.GetHashCode() = hash (x)
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? TreeOfPosition as y -> compare (x) (y)
| _ -> invalidArg "yobj" "cannot compare value of different types"
最終的に、leafpのリストの最大値(および最小)をその静的値(他の関数で計算)で取得したいだけです。
上のコードがコンパイルされています。ただし、これでのテスト:
let p = new Position()
p.Add(1,BLACK)
let a = LeafP(p,1)
let b = LeafP(p,2)
let biger = compare a b
printf "%d" biger
gethashcodeのオーバーライドの「|:?treeofposition as y-> compare(x)(y)」ラインでSystem.StackoverFlowExceptionを取得しました。
hubfs.netにスレッドがあります(http://cs.hubfs.net/forums/thread/15891.aspx)私は私のミニマックスについて話し合っています。ここでは、私の最新コードを見つけることができます(http://www.inf.ufrgs.br/~pmdusso/works/functional_implementation_minimax_fsharp.htm)
前もって感謝します、
ペドロデュッソ
まあ、私はそのアイデアを非常にはっきりと理解していましたが、それを機能させることはできません。葉のリストから最大値の葉を取得したいことを思い出してください(「list.max」:p)、実装していると思います CompareTo
また Equals
list.maxがそれらに動作するようにしますか、正しいですか?私はこのようなものを構成します:
let mycompare x y =
match x, y with
// Compare values stored as part of your type
| LeafP(_, n1), LeafP(_, n2) -> compare n1 n2
//| BranchP(_, l1), BranchP(_, l2) -> compare l1 l2 //I do not need Branch lists comparison
| _ -> 0 // or 1 depending on which is list...
[< CustomEquality;CustomComparison >]
type TreeOfPosition =
| LeafP of Position * int
| BranchP of Position * TreeOfPosition list
override x.Equals(yobj) =
match yobj with
| :? TreeOfPosition as y -> (x = y)
| _ -> false
override x.GetHashCode() = hash (x)
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? TreeOfPosition as y -> mycompare x y
| _ -> invalidArg "yobj" "cannot compare value of different types"
この方法で機能を整理している問題は、次のとおりです。
1)パターンの識別器「leafp」は定義されていません(leafp red-underlinged)
2)(77,39):エラーFS0039:値またはコンストラクター「mycompare」は定義されていません。位置{77,39}は、MyCompareコールの開始(GethashCode)に対応しています。
私は何が間違っているのですか?私は何がもっといいですか?
どうもありがとう、
ペドロデュッソ
編集3-解決しました
はい!私はあなたの答えを最終的に仕事に管理しています!
最終コードはこちらです:
[<CustomEquality;CustomComparison>]
type TreeOfPosition =
| LeafP of Position * int
| BranchP of Position * TreeOfPosition list
//Func: compare
//Retu: -1: first parameter is less than the second
// 0: first parameter is equal to the second
// 1: first parameter is greater than the second
static member mycompare (x, y) =
match x, y with
// Compare values stored as part of your type
| LeafP(_, n1), LeafP(_, n2) -> compare n1 n2
| _ -> 0 // or 1 depending on which is list...
override x.Equals(yobj) =
match yobj with
| :? TreeOfPosition as y -> (x = y)
| _ -> false
override x.GetHashCode() = hash (x)
interface System.IComparable with
member x.CompareTo yobj =
match yobj with
| :? TreeOfPosition as y -> TreeOfPosition.mycompare(x, y)
| _ -> invalidArg "yobj" "cannot compare value of different types"
フィードバックをお寄せいただきありがとうございます!
ペドロデュッソ
解決
まず第一に、あなたは例外を取得しています compare
関数はを呼び出します CompareTo
比較している値の方法(つまり、 x.ComaperTo(y)
)。使用している値を使用しています compare
のカスタム実装で CompareTo
(ランタイムまでに)比較するように求められる値であるため、これによりスタックオーバーフローが発生します。
実装する通常の方法 CompareTo
また Equals
あなたがあなたのタイプに保存するいくつかの値のみを比較することです。たとえば、次のようなものを書くことができます。
編集: :ヘルパー関数を書くことができます mycopare
比較を行うために(または単に変更することもできます CompareTo
実装)。ただし、関数を使用する場合は、タイプ宣言の内側に移動する必要があります(タイプについて知っているように - F#では、宣言の順序が重要であることに注意してください!)
それを書く1つの方法はこれです:
[<CustomEquality; CustomComparison >]
type TreeOfPosition =
| LeafP of Position * int
| BranchP of Position * TreeOfPosition list
override x.Equals(yobj) =
match yobj with
| :? TreeOfPosition as y ->
// TODO: Check whether both y and x are leafs/branches
// and compare their content (not them directly)
| _ -> false
override x.GetHashCode() = // TODO: hash values stored in leaf/branch
interface System.IComparable with
member x.CompareTo yobj =
// Declare helper function inside the 'CompareTo' member
let mycompare x y =
match x, y with
// Compare values stored as part of your type
| LeafP(_, n1), LeafP(_, n2) -> compare n1 n2
| BranchP(_, l1), BranchP(_, l2) -> compare l1 l2
| _ -> -1 // or 1 depending on which is list...
// Actual implementation of the member
match yobj with
| :? TreeOfPosition as y -> mycompare x y
| _ -> invalidArg "yobj" "cannot compare value of different types"
これは、すべての呼び出しがあるため、機能します compare
データの一部しか取っていないので、いくらか進歩しています。