Aka*_*ash 4 f# discriminated-union
假设我有以下DU:
type Something =
| A of int
| B of string * int
Run Code Online (Sandbox Code Playgroud)
现在我在这样的函数中使用它:
let UseSomething = function
| A(i) -> DoSomethingWithA i
| B(s, i) -> DoSomethingWithB s i
Run Code Online (Sandbox Code Playgroud)
这是有效的,但我必须解构DU才能将它传递给DoSomethingWith*函数.尝试将DoSomethingWithA定义为:我觉得很自然:
let DoSomethingWithA (a: Something.A) = ....
Run Code Online (Sandbox Code Playgroud)
但编译器抱怨未定义类型A.
似乎完全符合F#的哲学,希望将参数限制为Something.A,而不仅仅是任何旧的int,所以我只是以错误的方式去做?
需要注意的重要一点是,A和B是的构造相同类型Something.因此,如果您尝试单独使用A和B案例,您将获得无穷无尽的模式匹配警告.
IMO,解构所有DU的情况是一个好主意,因为它是类型安全的,并迫使你考虑处理那些甚至你不想要的情况.如果您必须以相同的方式重复解构DU,则可能会出现此问题.在这种情况下,在DU上定义map和fold功能可能是一个好主意:
let mapSomething fa fb = function
| A(i) -> fa i
| B(s, i) -> fb s i
Run Code Online (Sandbox Code Playgroud)
请参考@Brian的优秀Catamorphism系列来了解DUs上的折叠.
那也说你的榜样很好.解构后你真正处理的是什么string和int价值观.
您可以使用Active Patterns分别使用两种情况:
let (|ACase|) = function A i -> i | B _ -> failwith "Unexpected pattern B _"
let (|BCase|) = function B(s, i) -> (s, i) | A _ -> failwith "Unexpected pattern A _"
let doSomethingWithA (ACase i) = ....
Run Code Online (Sandbox Code Playgroud)
但推断的类型doSomethingWithA仍然相同,并且在传递B _给函数时会出现异常.所以做IMO是错误的.