什么';ActivePattern与System.Type的匹配有什么问题? 模块反射= [] 模块类型= 让我打字 let(| IsEqual | Isnt |)(t:Type):选择= 设t'=typeof then Some() 其他的 //printfn“不匹配%A到%A”选择类型“Choice”类型与类型“c->Choice”(使用外部F#编译器)不匹配
无论出于何种原因,这样的模式都被简单地禁止。只有具有一个结果的模式才能接受其他参数 这是合法的:什么';ActivePattern与System.Type的匹配有什么问题? 模块反射= [] 模块类型= 让我打字 let(| IsEqual | Isnt |)(t:Type):选择= 设t'=typeof then Some() 其他的 //printfn“不匹配%A到%A”选择类型“Choice”类型与类型“c->Choice”(使用外部F#编译器)不匹配,f#,pattern-matching,system.reflection,active-pattern,F#,Pattern Matching,System.reflection,Active Pattern,无论出于何种原因,这样的模式都被简单地禁止。只有具有一个结果的模式才能接受其他参数 这是合法的: module Reflection = [<RequireQualifiedAccess>] module Type = let isType<'a> = Unchecked.defaultof<'a> let (|IsEqual|Isnt|) (_:'a) (t:Type):Choice<unit,uni
module Reflection =
[<RequireQualifiedAccess>]
module Type =
let isType<'a> = Unchecked.defaultof<'a>
let (|IsEqual|Isnt|) (_:'a) (t:Type):Choice<unit,unit> =
let t' = typeof<'a>
if t = t' then IsEqual else Isnt
let (|TypeOf|_|) (_:'a) (t:Type) :unit option =
if t = typeof<'a> then Some ()
else
//printfn "did not match %A to %A" typeof<'a> t
None
open Reflection
match typeof<string> with
// compiles just fine
| Type.TypeOf (Type.isType:int) as x -> Some x.Name
// does not compile
| Type.IsEqual (Type.isType:string) as x -> Some x.Name
| _ -> None
let (|A|) x y = if x = y then 5 else 42
let f (A "foo" a) = printfn "%A" y
f "foo" // Prints "5"
f "bar" // Prints "42"
这是合法的:
module Reflection =
[<RequireQualifiedAccess>]
module Type =
let isType<'a> = Unchecked.defaultof<'a>
let (|IsEqual|Isnt|) (_:'a) (t:Type):Choice<unit,unit> =
let t' = typeof<'a>
if t = t' then IsEqual else Isnt
let (|TypeOf|_|) (_:'a) (t:Type) :unit option =
if t = typeof<'a> then Some ()
else
//printfn "did not match %A to %A" typeof<'a> t
None
open Reflection
match typeof<string> with
// compiles just fine
| Type.TypeOf (Type.isType:int) as x -> Some x.Name
// does not compile
| Type.IsEqual (Type.isType:string) as x -> Some x.Name
| _ -> None
let (|A|) x y = if x = y then 5 else 42
let f (A "foo" a) = printfn "%A" y
f "foo" // Prints "5"
f "bar" // Prints "42"
但就是这样。所有其他活动模式必须是无参数的。这两项都是非法的:
let (|B|_|) x y = if x = y then Some (y+5) else None
let f = function
| B 42 x -> printfn "%d" x
| _ -> printfn "try again"
f 42 // prints "47"
f 5 // prints "try again"
如果我不得不推测,我会说这与可预测的运行时性能有关。当模式匹配或不匹配时,编译器可以为每个参数值精确运行一次。但是,如果模式返回多个内容,其中一些内容出现在匹配表达式中,而其他内容则不存在,并且并非所有内容都具有相同的参数,那么找出进行最小数量函数调用的最佳方法将变得非常复杂。要添加到Fyodor的答案中,在概述有效的活动模式形式(至少比MSDN更详细)时,非常明确-有关详细信息,请参见第7.2.3段活动模式 五份有效表格为:
- 单个案例-
(|案例名称|)inp
- 部分-
(|案例名称| |)inp
- 多案例-
(|案例名称1 |…|案例名称n |)inp
- 带参数的单个大小写-
(| CaseName |)arg1。。。argn inp
- 带有参数的分部-
(| CaseName | |)arg1。。。argn inp
这里最相关的是,无法将多案例模式与其他参数结合起来 我并没有注意到,也许它与可证明的穷举模式有关,若你们制作了一个参数化的活动模式,编译器可能是在撒谎,因为它不一定能够辨别它是否真的穷举。是的,这可能是一个比我更好的解释。不确定。虽然我打开了它-规范在运行时行为上已经故意含糊不清:
在解析单个整体模式匹配期间,可以针对同一模式输入多次执行活动模式函数。针对特定模式输入执行活动模式功能的精确次数取决于实现。
(来自第7.2.3段)