Pro*_*ool 7 f# record pattern-matching
所以我已经记录在我的F#旅程中,起初它们看起来相当危险.起初这看起来很聪明:
type Card = { Name : string;
Phone : string;
Ok : bool }
let cardA = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false }
Run Code Online (Sandbox Code Playgroud)
cardA与卡匹配的想法.更不用说这里简化的模式匹配:
let withTrueOk =
list
|> Seq.filter
(function
| { Ok = true} -> true
| _ -> false
)
Run Code Online (Sandbox Code Playgroud)
问题是:
type Card = { Name : string;
Phone : string;
Ok : bool }
type CardTwo = { Name : string;
Phone : string;
Ok : bool }
let cardA = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false }
Run Code Online (Sandbox Code Playgroud)
cardA现在属于CardTwo类型,我猜这与F#按顺序运行一切有关.
现在这可能是一个不可能的情况,因为可能永远不会有相同的签名承担两种类型的机会,但这是一种可能性.
录制的东西只有有限的用途,还是我只是在想这个?
svi*_*ick 19
它们并不危险,它们不仅限于使用.
我认为很少有两种类型的成员具有相同的成员.但是如果遇到这种情况,您可以限定要使用的记录类型:
let cardA = { Card.Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false }
Run Code Online (Sandbox Code Playgroud)
记录对于创建(大多数)不可变数据结构非常有用.而且,只需更改一些字段即可轻松创建副本的事实也很棒:
let cardB = { cardA with Ok = true }
Run Code Online (Sandbox Code Playgroud)
Dan*_*iel 12
我同意,记录字段作为封闭模块/命名空间的成员起初看起来很奇怪,它们来自更传统的OO语言.但是F#在这里提供了相当大的灵活性.我想你会发现只有做作的情况会导致问题,例如两个记录
第一种情况永远不会发生.后者可以通过具有记录A字段的记录B来解决.
您只需要一个字段可以区分两个字段.除此之外,定义可以是相同的.
type Card =
{ Name : string
Phone: string
Ok : bool }
type CardTwo =
{ Name : string
Phone: string
Age : int }
let card = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false }
let cardTwo = { Name = "Alf" ; Phone = "(206) 555-0157" ; Age = 21 }
Run Code Online (Sandbox Code Playgroud)
模式匹配也非常灵活,因为您只需匹配足够的字段以区别于其他类型.
let readCard card =
match card with
| { Ok = false } -> () //OK
| { Age = 21 } -> () //ERROR: 'card' already inferred as Card, but pattern implies CardTwo
Run Code Online (Sandbox Code Playgroud)
顺便提一下,使用类型注释可以轻松修复您的场景:
let cardA : Card = { Name = "Alf" ; Phone = "(206) 555-0157" ; Ok = false }
Run Code Online (Sandbox Code Playgroud)
为了让您了解F#提供的内容,我只想提一下OCaml中没有完全限定的记录访问者.因此,要区分具有相同字段的记录类型,必须将它们放入子模块并使用模块前缀引用它们.
所以你在F#中的情况要好得多.使用记录访问器可以快速解决类似记录类型之间的任何歧义:
type Card = { Name: string;
Phone: string;
Ok: bool }
type CardSmall = { Address: string;
Ok: bool }
let withTrueOk list =
list
|> Seq.filter (function
| { Card.Ok = true} -> true (* ambiguity could happen here *)
| _ -> false)
Run Code Online (Sandbox Code Playgroud)
而且,F#记录完全没有限制.它提供了很多开箱即用的好功能,包括模式匹配,默认不变性,结构相等等.