为什么在有区别的联合中不允许let绑定?我假设它与在默认构造函数中执行let绑定有关?
另外,任何关于我如何重写AI_Choose的建议都将不胜感激。我希望将加权优先级与AI保持在一个元组中。我的想法是让AI_Weighted_Priority继承AI_Priority并覆盖Choose。我不想处理不同长度的压缩列表(不好的做法是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)发布于 2009-08-26 23:31:13
允许在有区别的联合中进行"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)变得更容易,因此这可能是设计应用程序时要考虑的第一件事。
发布于 2009-08-26 04:56:14
对于任何感兴趣的人,我最终从一个抽象基类派生了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发布于 2009-10-06 04:35:43
重新查看这段代码后,我最终采纳了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)https://stackoverflow.com/questions/1332299
复制相似问题