سؤال

لماذا تدع الروابط غير مسموح بها في الاتحاد التمييز؟ أفترض أنه يجب القيام به مع ترك الارتباطات التي يتم تنفيذها في منشئ افتراضي؟

في ملاحظة ثانوية، أي اقتراحات حول كيفية إعادة كتابة AI_Choose سيكون موضع تقدير. أريد أن أبقي الأولوية المرجحة في tuple مع منظمة العفو الدولية. فكرتي هي أن يكون AI_Weighted_Priority يرث AI_Priority وتجاوز الاختيار. لا أريد التعامل مع قوائم Zipping بأطوال مختلفة (ممارسة سيئة للغاية)

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)
هل كانت مفيدة؟

المحلول

من المنطقي السماح ب "دع" ملزمة داخل النقابات التمييزية. أعتقد أن السبب في أنه غير ممكن هو أن النقابات التمييزية لا تزال قائمة على تصميم OCAML بينما تأتي الكائنات من World .NET. F # تحاول دمج هذين قدر الإمكان، ولكن ربما يمكن أن يذهب أبعد من ذلك.

على أي حال، يبدو لي أنك تستخدم الاتحاد التمييز فقط لتنفيذ بعض السلوك الداخلي لل AI_Choose يكتب. في هذه الحالة، يمكنك إعلان اتحاد تميز بشكل منفصل واستخدامه لتنفيذ نوع الكائن.

أعتقد أنك يمكن أن تكتب شيئا مثل هذا:

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 (...)

الفرق الرئيسي بين التسلسل الهرمي للفئة والاتحادات التمييز هو عندما يتعلق الأمر بالاسعة. تسهل الفصول الدراسية إضافة أنواع جديدة أثناء التمييز بين الاتحادات التي تجعل من الأسهل إضافة وظائف جديدة تعمل مع النوع (في حالتك AichooseOptions)، لذلك ربما يكون هذا أول شيء يجب مراعاته عند تصميم التطبيق.

نصائح أخرى

لأي شخص مهتم انتهى بي الأمر AI_Priority و AI_Weighted_Priority من فئة قاعدة مجردة.

[<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

إعادة النظر في هذا الرمز، انتهى بي الأمر إلى اتخاذ اقتراح توماس الذي اتضح أنظف الكثير.

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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top