我刚刚注意到F#允许我使用带有文字和其他模式的let绑定,如下所示:
let fib 0 = 1 let exists item [] = false let car (hd :: tl) = hd let cdr (hd :: tl) = tl
F#正确地将这些函数解释为一种模式匹配,因为我给出了以下警告:
警告1此表达式的不完整模式匹配.例如,值"1"将不匹配
警告2此表达式的不完整模式匹配.例如,值"[_]"将不匹配
等等
这些函数按预期工作,但我想用这种样式定义一个具有完全模式匹配的函数,但是我在F#手册中找不到关于这种替代模式匹配语法的任何信息.
我知道我可以使用let whatever = function ...
并let whatever x = match x with ...
获得我想要的结果,但我刚刚发现了另一种模式匹配的语法,如果我不知道如何使用它,它会永远唠叨我.
如何使用上面显示的替代模式匹配语法编写函数?
AFAIK,F#中没有办法声明具有相同名称和不同模式匹配签名的多个let绑定.我相信与你正在寻找的最接近的构造是一个函数规则表达式.
以这个例子为汽车
let car = function | hd::tl -> hd | [] -> failwith "empty list"
JaredPar是对的,F#没有Haskell在这里做的句法形式.
F#表单主要用于打开单个案例区分联合或用于定义不完整匹配的函数(例如在空列表中失败的'car'示例).这只是一个事实的结果,实际上语言中的所有名称绑定都是通过模式完成的; 由于您所描述的确切原因,这种句法形式(使用参数上的模式定义函数)在实践中通常不太有用.
我认为Haskell在语法形式方面做了很多比ML更好的事情,但F#的根源是ML.好处是有一个很好的F#子集与OCaml交叉编译(它帮助引导了F#语言和用户社区); 缺点是F#被一些丑陋/有限的语法"卡住"了.
显然,F#的模式匹配比我们在共同开发中使用的方式更强大.
首先,您可以一次绑定多个值.通常情况下,您将使用List.partition
:
let data = [7;0;0;0;1;0;1;1;1;1;0;0;1;1;0] let ones, others = data |> List.partition ((=) 1) // bind two values
作为旁注,您可以将多个标识符绑定到相同的值:
let (a & b) = 42 // a = 42; b = 42
让我们从简单的let
绑定开始,为了简单起见.
let hd::tl = data
警告FS0025:此表达式上的不完整模式匹配.例如,值"[]"可以指示模式未涵盖的情况.
为了缓解这种情况,我们必须为空列表添加另一个案例:
let (hd::tl) | [] = data
错误FS0018:此"或"模式的两边绑定不同的变量集
这是真的; 如果是空列表,hd
并tl
保持未绑定状态.tl
使用相同的空列表绑定很容易:
let (hd::tl) | ([] as tl) = data
但是,错误错误FS0018不会消失.实际上,我们还必须提供一些"默认"值hd
.
以下脏技巧会做到这一点.
let (hd::tl, _) | ([] as tl , hd) = data, 42
如果列表不为空,或者在第二个值中提供额外值,则上面的行将绑定hd
到data
头部.tuple
注意:我还没有发现嵌入的方式42
进入let
结构.
最后,car
功能相同:
let car ((hd::tl, _) | ([] as tl, hd)) = hd let foo = car(data, 42) // foo = 7 let bar = car([], 42) // bar = 42