2009-08-26 55 views
6

为什么在受歧视的工会中不允许绑定?我认为它必须与让绑定在默认构造函数中执行?歧视联盟和让绑定?

在次要记录中,有关如何重写AI_Choose的建议将不胜感激。我想用AI保持加权优先级。我的想法是让AI_Weighted_Priority继承AI_Priority并覆盖选择。我不想处理荏苒不同长度的列表(不好的做法IMO)

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) 

回答

2

允许在被区分的联合中“let”绑定是有意义的。我认为不可能的原因是受歧视的工会仍然基于OCaml设计,而对象来自.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),所以这可能是设计应用程序时首先要考虑的事情。

3

任何有兴趣我结束了从抽象基类派生AI_PriorityAI_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 
3

重温这段代码我最终采取了Tomas的建议,结果证明它更加清洁。

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)