对活动模式感到困惑

Gre*_*Ros 3 .net f# functional-programming

我理解如何在F#中定义和使用活动模式,包括部分活动模式,以及可用的不同类型的模式.例如

let (|Big|Small|) animal = if animal.IsBig then Big(animal) else Small(animal)
let f = function | Big(_) -> "big" |Small(_) -> "small
Run Code Online (Sandbox Code Playgroud)

但是,我很困惑在let绑定,参数和其他地方使用活动模式和有区别的联合.例如,MSDN具有以下代码:

let GetSubstring1 (Slice(p0, p1, text)) = 
    printfn "Data begins at %d and ends at %d in string %s" p0 p1 text
    text.[p0..p1]
Run Code Online (Sandbox Code Playgroud)

这让我有点困惑.

一个具体问题.假设我有歧视的联盟,

type Union = A of int * int | B of int
Run Code Online (Sandbox Code Playgroud)

我可以以某种方式制作一个只接受的功能Union.A,例如

let f (A(a, b)) = a + b
Run Code Online (Sandbox Code Playgroud)

在这种情况下,它告诉我有无与伦比的模式.有没有办法满足它?

Tom*_*cek 8

如@ildjarn所述,这适用于所有模式.它们可以出现在match子句的情况下(并且在function其中类似),但也可以在let绑定函数的参数声明中出现,甚至可以在let值绑定中出现.

关键的区别在于let,您只想使用始终成功的完整模式.这是不需要的matchfunction,因为有多个条款,因此,如果第一个失败,匹配可继续尝试下一个.

例如,以下完整模式int将其作为以下内容返回string:

let (|AsString|) (n:int) = n.ToString()
Run Code Online (Sandbox Code Playgroud)

以下是一些如何使用它的方法:

let (AsString s) = 42         // Defines a value 's' of type string
match 3 with AsString s -> s  // Returns a value "3" of type string
let convert (AsString s) = s  // Defines a function 'int -> string'
let convert = function AsString s -> s  // Same as the previous line
Run Code Online (Sandbox Code Playgroud)

编辑:要回答你的第二个问题,如果你使用let具有不完整的模式(即只接受一个可识别联合的单一情况下),然后你得到一个编译器警告,该代码可以在运行时失败(如果你与其他歧视叫它工会案例):

let f (A(a, b)) = a + b      // This gives compile-time warning
f (B 42)                     // This will fail at runtime 
Run Code Online (Sandbox Code Playgroud)

如果需要定义仅适用于其中一种情况的函数,则需要定义单独的类型.

type AInfo = int * int 
type Union = A of AInfo | B of int  
Run Code Online (Sandbox Code Playgroud)

然后你可以编写一个只需要的函数AInfo(但你仍然可以Union在两个选项代表有效输入的地方使用).