Dev*_*ard 3 f# records discriminated-union
我目前正在研究F#,同时,有点努力想要了解歧视的工会和记录究竟如何运作.
我想知道如何从<T>类型列表中更新一些值?
type Position =
| Location of (int * int)
type Ship =
{
Position : Position;
Projectiles : List<Position>;
}
Run Code Online (Sandbox Code Playgroud)
我创建了一个船的实例:
let aShip =
{
Position: Location(1,5);
Projectiles: [Location(1,1);Location(2,5)]
}
Run Code Online (Sandbox Code Playgroud)
现在,我试图绕过弹丸,但我明白了:
for elem in aShip.Projectiles do
printfn "%A" elem
// prints out
Location(1,1)
Location(2,5)
Run Code Online (Sandbox Code Playgroud)
但我只想得到值(1,1)和(2,5),我将如何实现这一目标?
识别联合可以解构通过提供一个模式,在它的一些地方被标识符所占据.然后,编译器将生成尝试将此模式与数据匹配的代码,并将数据点绑定到适当的标识符.例如:
let loc = Location (1,2)
let (Location (x,y)) = loc
Run Code Online (Sandbox Code Playgroud)
对于第二行,编译器将生成代码,以" 确保这是一个Location
,然后将第一个int绑定到name x
,第二个int 绑定到namey
"
或者,您可以使用更详细的match
语法:
let x = match loc with Location(x,y) -> x
Run Code Online (Sandbox Code Playgroud)
对于您的具体情况,这是过度的,但对于具有多个案例的受歧视的工会,match
是处理它们的唯一方法,例如:
type Position =
| Location of int*int
| Unknown
let xOrZero =
match loc with
| Location(x,y) -> x
| Unknown -> 0
Run Code Online (Sandbox Code Playgroud)
上面的例子演示了模式如何出现在let
-bindings和match
表达式中,但这不是全部.在F#中,几乎所有你认为是"变量声明"的东西实际上都是一种模式.这只是大部分时间模式都是微不足道的let x = 5
,但是它们不一定是 - 例如let x,y = 5,6
从上述的必然结果是,elem
在for elem in ...
是也图案.这意味着您可以对元素进行结构化:
for Location(x,y) in aShip.Projectiles do
printfn "%d,%d" x y
Run Code Online (Sandbox Code Playgroud)
或者,如果你想提取对作为一个整体,而不是x
与y
个别,这也是可能的:
for Location xy in aShip.Projectiles do
printfn "%A" xy
Run Code Online (Sandbox Code Playgroud)