Vag*_*lov 5 generics f# pattern-matching
我有以下代码:
type Message<'a> = | Message of 'a
let handleMessage message =
match box message with
| :? Message<_> -> printfn "Message"
| _ -> printfn "Not message"
let handleMessageEx message =
match box message with
| :? Message<int> -> printfn "Message"
| _ -> printfn "Not message"
handleMessage <| Message 1
handleMessage <| Message (1 :> obj)
handleMessageEx <| Message 1
Run Code Online (Sandbox Code Playgroud)
F# Interactive 中的输出如下:
Not message
Message
Message
Run Code Online (Sandbox Code Playgroud)
为什么第一个语句会导致“Not message”?即,当匹配装箱值时,F# 无法检测到它是泛型类型 Message<_> ,除非我指定底层类型,否则它将其设置为 object(因此匹配失败(消息 1))。
每当您看到_类型参数时,请将其视为您不关心的新类型参数。如果我们相应地调整你的第一个定义:
let handleMessage message =
match box message with
| :? Message<'_a> -> printfn "Message"
| _ -> printfn "Not message"
Run Code Online (Sandbox Code Playgroud)
然后编译器给了我们这个有用的线索:
警告 FS0064:此构造导致代码不如类型注释指示的通用。类型变量“_a”已被限制为“obj”类型。
问题是类型参数必须被赋予一些特定的值,但是编译器没有基础来选择一个值,所以它默认为obj,这不是你想要的。
没有开箱即用的好方法,但您可以创建一个活动模式来稍微简化体验:https ://stackoverflow.com/a/2140485/82959 。