首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有区别的Union & let绑定?

有区别的Union & let绑定?
EN

Stack Overflow用户
提问于 2009-08-26 04:23:06
回答 3查看 1.4K关注 0票数 6

为什么在有区别的联合中不允许let绑定?我假设它与在默认构造函数中执行let绑定有关?

另外,任何关于我如何重写AI_Choose的建议都将不胜感激。我希望将加权优先级与AI保持在一个元组中。我的想法是让AI_Weighted_Priority继承AI_Priority并覆盖Choose。我不想处理不同长度的压缩列表(不好的做法是imo)。

代码语言:javascript
复制
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)
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-08-26 23:31:13

允许在有区别的联合中进行"let“绑定是有意义的。我认为这是不可能的,因为区别对待的联合仍然基于OCaml设计,而对象来自.NET世界。F#正在尝试尽可能多地集成这两者,但它可能会走得更远。

无论如何,在我看来,您使用区分联合只是为了实现一些AI_Choose类型的内部行为。在这种情况下,您可以单独声明一个有区别的联合,并使用它来实现对象类型。

我相信你可以写成这样:

代码语言:javascript
复制
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)变得更容易,因此这可能是设计应用程序时要考虑的第一件事。

票数 2
EN

Stack Overflow用户

发布于 2009-08-26 04:56:14

对于任何感兴趣的人,我最终从一个抽象基类派生了AI_PriorityAI_Weighted_Priority

代码语言:javascript
复制
[<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
EN

Stack Overflow用户

发布于 2009-10-06 04:35:43

重新查看这段代码后,我最终采纳了Tomas的建议,结果干净多了。

代码语言:javascript
复制
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)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1332299

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档