重载F#活动模式
我对F#和活动模式相当陌生,我遇到了一个无法解释的异常重载F#活动模式,f#,overloading,active-pattern,F#,Overloading,Active Pattern,我对F#和活动模式相当陌生,我遇到了一个无法解释的异常 module Eval = let (|Bet|Pass|) (test:BetChoice) = match test with | BetChoice.Bet -> Bet | BetChoice.Pass -> Pass let (|NoBet|Bet|Pass|) (test:Nullable<BetChoice>) : Choice<unit, unit, u
module Eval =
let (|Bet|Pass|) (test:BetChoice) =
match test with
| BetChoice.Bet -> Bet
| BetChoice.Pass -> Pass
let (|NoBet|Bet|Pass|) (test:Nullable<BetChoice>) : Choice<unit, unit, unit> =
match test.HasValue with
| true -> match test.Value with
| BetChoice.Bet -> Bet
| BetChoice.Pass -> Pass
| false -> NoBet
let FlipByWinner ((value:int), (awins:bool)) =
match awins with
| true -> (value, -value)
| false -> (-value, value)
let Evaluation (awins:bool) (player11:BetChoice) (player21:BetChoice) (player12:Nullable<BetChoice>) =
match player11 with
| Pass -> match player21 with
| Pass -> FlipByWinner(1, awins)
| Bet-> match player12 with
| Bet -> FlipByWinner(2, awins)
| Pass -> FlipByWinner(1, false)
| NoBet -> raise (System.ArgumentException("invalid strategy"))
| Bet -> match player21 with
| Bet -> FlipByWinner (2, awins)
| Pass -> FlipByWinner (1, false)
模块评估=
让(|打赌|通过|)(测试:BetChoice)=
匹配测试
|BetChoice.Bet->Bet
|BetChoice.Pass->Pass
let(| NoBet | Bet | Pass |)(测试:可为空):选择=
将test.HasValue与
|true->将测试值与
|BetChoice.Bet->Bet
|BetChoice.Pass->Pass
|假->小号
让FlipByWinner((值:int),(awins:bool))=
与…搭配
|true->(值,-值)
|假->(-value,value)
let评估(awins:bool)(player11:BetChoice)(player21:BetChoice)(player12:Nullable)=
将运动员11与
|传球->与21号选手比赛
|通过->FlipByWinner(1,awins)
|下注->将玩家12与
|下注->FlipByWinner(2,awins)
|通过->FlipByWinner(1,错误)
|NoBet->raise(System.ArgumentException(“无效策略”))
|下注->将玩家21与
|下注->FlipByWinner(2,awins)
|通过->FlipByWinner(1,错误)
这不能编译。
只要稍加调整,我就能让它按预期工作,但我不知道到底发生了什么,这让我有点紧张。。。
第二个模式可以重命名为“(|NoBet | Bet1 | Pass1 |)”,它的关联模式在整个代码中都发生了更改,然后它就可以工作了,但我不明白为什么会出现类型不匹配异常
还有没有一种很好的方法来处理两个几乎相同但不完全相同的活动模式?看来应该有办法把普通的东西综合起来。
(作为旁注,看起来缩进在复制/粘贴过程中被弄乱了,这是模块评估的一部分。)是的,第一个问题非常合理。同一命名空间中不能有两个同名的活动模式标记。这与F#编译器如何实际生成活动模式名有关。如果查看reflector,则生成的代码用于:
type Alpha = Foo | Bar
let (|Foo|Bar|) = ...
这是非常不同的,尽管概念上活跃的模式和歧视性的结合是非常相似的概念
不管怎么说,你要问的问题是,如果你有两组活动模式,它们大多相似/不同,你该怎么办。我建议你们使用部分活动模式。看这个
在本例中,您似乎需要以下内容:
let (|IsBet|_|) = ...
let (|IsPass|_|) = ...
这样,您可以同时对玩家11和玩家21进行模式匹配,例如:
match player11, player21 with
| IsPass & IsPass -> ...
| IsPass & IsBet -> ...
| IsBet & IsPass -> ...
| IsBet & IsBet -> ...
这将大大有助于清理代码。因此,模式返回布尔值,这样就不必担心可为null的类型,同时也使代码更加精简……不确定这是否有意义,但感谢,这很有帮助。实际上,部分活动模式可以返回任何形式的数据。例如,IsBet模式可以返回下注金额。使用| IsBet amount with amount>100->printfn“Bet over$100!”匹配player11因为你说你是F#的新手,我想如果你不需要与其他.NET语言交互,我会建议使用选项类型而不是可为null的类型,因为使用匹配选项会更好。