[英]overloading F# active patterns
我对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, 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)
这不会编译。 稍作调整,我就可以按预期进行工作,但是我不知道到底发生了什么,这一事实使我有些紧张...第二种模式可以重命名为“((| NoBet | Bet1 | Pass1 | )”,并且在整个代码中更改了与之相关的模式,然后就可以了,但是我真的不明白为什么它会有类型不匹配的异常。
还有一种好的方法来处理两个几乎完全相同但不太完全相同的活动模式吗? 似乎应该有一种方法可以将常见的东西放在一起。 (作为附带说明,缩进看起来像是在复制/粘贴中弄乱了,这完全是Eval模块的一部分)。
是的,第一个问题很有意义。 在同一个名称空间中,不能有两个具有相同名称的活动模式标签。 这与F#编译器实际生成活动模式名称的方式有关。 如果查看反射器,将为以下内容生成代码:
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 -> ...
这对清理代码大有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.