3

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

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

但是,我对在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]

这让我有点困惑。

一个具体的问题。假设我有歧视工会,

type Union = A of int * int | B of int

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

let f (A(a, b)) = a + b

在这种情况下,它告诉我有不匹配的模式。有办法满足吗?

4

1 回答 1

8

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

关键区别在于let,您只想使用始终成功的完整模式。matchor不需要这个function,因为有多个子句,所以如果第一个失败,匹配可以继续并尝试下一个。

例如,以下完整模式int将其作为 a 接受并返回string

let (|AsString|) (n:int) = n.ToString()

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

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

编辑:要回答您的第二个问题,如果您使用let完整的模式(即只接受一个可区分联合的情况),那么您会收到编译器警告,并且代码可能在运行时失败(如果您使用其他可区分的方式调用它)工会案例):

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

如果您需要定义一个仅适用于其中一种情况的函数,那么您需要定义一个单独的类型。

type AInfo = int * int 
type Union = A of AInfo | B of int  

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

于 2012-10-04T23:17:05.457 回答