Frage

Warum Bindungen werden lassen nicht in einer diskriminierte Vereinigung erlaubt? Ich nehme an, es hat mit let-Bindungen zu tun, in einem Standard-Konstruktor ausgeführt werden?

Auf einer sekundäre Anmerkung Vorschläge, wie ich AI_Choose umschreiben könnte würden geschätzt. Ich möchte mit der KI die gewichtete Priorität in einem Tupel zu halten. Meine Idee ist AI_Weighted_Priority erben AI_Priority zu haben, und überschreiben wählen. Ich will nicht mit zippen Listen unterschiedlicher Länge bewältigen (imo schlechte Praxis.)

open AI

type Condition =
    | Closest of float
    | Min
    | Max
    | Average
    member this.Select (aiListWeight : list<AI * float>) =
        match this with
        | Closest(x) -> 
            aiListWeight 
            |> List.minBy (fun (ai, priority) -> abs(x - priority))
        | Min -> aiListWeight |> List.minBy snd
        | Max -> aiListWeight |> List.maxBy snd
        | Average -> 
            let average = aiListWeight |> List.averageBy snd
            aiListWeight 
            |> List.minBy (fun (ai, priority) -> abs(average - priority))

type AI_Choose =
    | AI_Priority of list<AI> * Condition
    | AI_Weighted_Priority of list<AI * float> * Condition

    // I'm sad that I can't do this    
    let mutable chosen = Option<AI>.None

    member this.Choose() =
        match this with
        | AI_Priority(aiList, condition) -> 
            aiList 
            |> List.map (fun ai -> ai, ai.Priority())
            |> condition.Select
            |> fst
        | AI_Weighted_Priority(aiList, condition) -> 
            aiList 
            |> List.map (fun (ai, weight) -> ai, weight * ai.Priority())
            |> condition.Select
            |> fst

    member this.Chosen
        with get() = 
            if Option.isNone chosen then
                chosen <- Some(this.Choose())
            chosen.Value
        and set(x) =
            if Option.isSome chosen then
                chosen.Value.Stop()
            chosen <- Some(x)
            x.Start()

    interface AI with
        member this.Start() =
            this.Chosen.Start()
        member this.Stop() =
            this.Chosen.Stop()
        member this.Reset() =
            this.Chosen <- this.Choose()
        member this.Priority() =
            this.Chosen.Priority()
        member this.Update(gameTime) =
            this.Chosen.Update(gameTime)
War es hilfreich?

Lösung

würde es Sinn machen „lassen“ Bindung innerhalb diskriminiert Gewerkschaften zu ermöglichen. Ich denke, den Grund, warum es nicht möglich ist, ist, dass diskriminierte Gewerkschaften nach wie vor auf dem OCaml-Design basieren, während Objekte aus der .NET-Welt kommen. F # versucht, diese beiden so viel wie möglich zu integrieren, aber es könnte wohl weiter gehen.

Wie auch immer, es scheint mir, dass Sie die diskriminieren Vereinigung verwenden nur einige interne Verhalten des AI_Choose Typ zu implementieren. In diesem Fall könnten Sie eine diskriminierte Vereinigung separat deklarieren und es verwenden, um den Objekttyp zu implementieren.

Ich glaube, Sie so etwas schreiben könnte:

type AiChooseOptions =
    | AI_Priority of list<AI> * Condition
    | AI_Weighted_Priority of list<AI * float> * Condition

type AiChoose(aiOptions) = 
    let mutable chosen = Option<AI>.None
    member this.Choose() =
        match aiOptions with
        | AI_Priority(aiList, condition) -> (...)
        | AI_Weighted_Priority(aiList, condition) -> (...)
    member this.Chosen (...)
    interface AI with (...)

Der wesentliche Unterschied zwischen Klassenhierarchie und diskriminierte Gewerkschaften, wenn es um Dehnbarkeit kommt. Klassen machen es einfacher, neue Typen hinzufügen, während diskriminieren Gewerkschaften machen es einfacher, neue Funktionen hinzuzufügen, dass die Arbeit mit der Art (in Ihrem Fall AiChooseOptions), so dass wahrscheinlich das erste, was ist zu beachten, wenn die Entwicklung neuer Anwendungen.

Andere Tipps

Für alle Interessierten ich am Ende AI_Priority und AI_Weighted_Priority von einer abstrakten Basisklasse abgeleitet wird.

[<AbstractClass>]
type AI_Choose() =
    let mutable chosen = Option<AI>.None

    abstract member Choose : unit -> AI

    member this.Chosen
        with get() = 
            if Option.isNone chosen then
                chosen <- Some(this.Choose())
            chosen.Value
        and set(x) =
            if Option.isSome chosen then
                chosen.Value.Stop()
            chosen <- Some(x)
            x.Start()

    interface AI with
        member this.Start() =
            this.Chosen.Start()
        member this.Stop() =
            this.Chosen.Stop()
        member this.Reset() =
            this.Chosen <- this.Choose()
        member this.Priority() =
            this.Chosen.Priority()
        member this.Update(gameTime) =
            this.Chosen.Update(gameTime)

type AI_Priority(aiList : list<AI>, condition : Condition) =
    inherit AI_Choose()
    override this.Choose() =
        aiList 
        |> List.map (fun ai -> ai, ai.Priority())
        |> condition.Select
        |> fst

type AI_Weighted_Priority(aiList : list<AI * float>, condition : Condition) =
    inherit AI_Choose()
    override this.Choose() =
        aiList 
        |> List.map (fun (ai, weight) -> ai, weight * ai.Priority())
        |> condition.Select
        |> fst

Neubetrachtung diesen Code I Tomas Vorschlag nimmt schließlich die viel sauberer geworden ist.

type AiChooseOptions =
    | Priority of List<AI * Priority>
    | WeightedPriority of List<AI * Priority * float>
    member this.Choose(condition : Condition) =
        match this with
        | Priority(list) ->
            list 
            |> List.map (fun (ai, priority) -> ai, priority.Priority())
            |> condition.Select
        | WeightedPriority(list) ->
            list 
            |> List.map (fun (ai, p, weight) -> ai, p.Priority() * weight)
            |> condition.Select

type AiChoose(condition, list : AiChooseOptions ) =
    let mutable chosen = Unchecked.defaultof<AI>, 0.0

    interface AI with
        member this.Update(gameTime) =
            (fst chosen).Update(gameTime)

    interface Priority with
        member this.Priority() =
            chosen <- list.Choose(condition)
            (snd chosen)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top