什么';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段)