Facebook Twitter LinkedIn E-mail
magnify
Home F# F#开发教程(10):函数化编程(九)
formats

F#开发教程(10):函数化编程(九)

Published on 2016 年 08 月 28 日

活跃模式

活跃模式(active patterns)提供了一个灵活的方式来使用F#中的模式匹配。它允许你积极主动地调用一个函数来判断输入是否匹配,这也是它被称为“活跃”模式的原因。
所有的活跃模式根据输入进行一个的计算来判断是否有匹配发生。有两种类型的活跃模式:
完全活跃模式 支持你将匹配拆分成有限的几种情况。
部分活跃模式 有匹配或匹配失败两种情况之一。

完全活跃模式

定义完全活跃模式和定义函数的语法比较近似,关键的差别是完全活跃模式的标志符包含在香蕉括号(banana brackets)中.香蕉括号是括号加竖直线(||).不同的匹配类型以竖直线分隔。活跃模式的主体部分为一F#函数,该函数必须返回定义在香蕉括号中所有类型。在返回所有的类型数据时可以返回额外的数据,如同联合类型一样。

> open System;;
> let (|Bool|Int|Float|String|) input =
-     let success,res = Boolean.TryParse input
-     if success then Bool(res)
-     else
-         let success,res = Int32.TryParse input
-         if success then Int(res)
-         else
-             let success,res = Double.TryParse input
-             if success then Float(res)
-             else String(input);;

val ( |Bool|Int|Float|String| ) :
  input:string -> Choice<bool,int,float,string>

> let printInputWithType input =
-     match input with 
-     | Bool b -> printfn "Boolean: %b" b
-     | Int i -> printfn "Integer: %i" i
-     | Float f -> printfn "Floating point: %f" f
-     | String s -> printfn "String: %s" s;;

val printInputWithType : input:string -> unit

> printInputWithType "true";;
Boolean: true
val it : unit = ()
> printInputWithType "12";;  
Integer: 12
val it : unit = ()
> printInputWithType "-12.3";;
Floating point: -12.300000
val it : unit = ()

部分活跃模式

部分活跃模式定义和完全活跃模式定义接近,所不同是部分活跃模式的香蕉括号内只有两种情况,一个是有匹配,一个无匹配。此外完全活跃模式可以保证返回香蕉括号中定义的类型之一,而部分活跃模式可能有不匹配情况的发送,因此它的返回值得类型是可选类型Option.
所有活跃模式出输入参数外,还可以有额外的参数,这想额外参数必须定义在输入参数的前面,比如

open System.Text.RegularExpressions
// the definition of the active pattern
let (|Regex|_|) regexPattern input =
    // create and attempt to match a regular expression
    let regex = new Regex(regexPattern)
    let regexMatch = regex.Match(input)
    // return either Some or None
    if regexMatch.Success then
        Some regexMatch.Value
    else
        None

// function to print the results by pattern
// matching over different instances of the
// active pattern
let printInputWithType input =
    match input with
    | Regex "$true|false^" s -> printfn "Boolean: %s" s
    | Regex @"$-?\d+^" s -> printfn "Integer: %s" s
    | Regex "$-?\d+\.\d*^" s -> printfn "Floating point: %s" s
    | _ -> printfn "String: %s" input
// print the results
printInputWithType "true"
printInputWithType "12"
printInputWithType "-12.1"

完全活跃模式的行为和联合类型非常一致,意味着如果匹配规则没有覆盖所有情况时会给出警告。而部分活跃模式,需要最后定义个通配规则,部分活跃模式也它的优点,也就是可以将多个规则串接在一起,比如上面例子中定义了三个不同的正规语法匹配。

 
Tags:
 Share on Facebook Share on Twitter Share on Reddit Share on LinkedIn