f# - 如何在 F# 中更新 <T> 类型列表中的值?

标签 f# records discriminated-union

我目前正在学习 F#,与此同时,有点难以掌握受歧视的联合和记录的确切工作原理。

我想知道如何从 <'T> 类型的列表中更新一些值?

我的代码

type Position =
| Location of (int * int)

type Ship = 
{
    Position : Position;
    Projectiles : List<Position>; 
}

我创建了一艘船的实例:

let aShip = 
{
    Position: Location(1,5);
    Projectiles: [Location(1,1);Location(2,5)] 
}

现在,我尝试遍历射弹,但我明白了:

for elem in aShip.Projectiles do
    printfn "%A" elem

// prints out
Location(1,1)
Location(2,5)

但我只想取回值 (1,1) 和 (2,5),我该如何实现?

最佳答案

通过提供一个模式,其中的某些位置被标识符占据,可以解构可区分的联合。然后,编译器将生成代码,尝试将此模式与数据匹配,并将数据点绑定(bind)到适当的标识符。例如:

let loc = Location (1,2)
let (Location (x,y)) = loc

对于第二行,编译器将生成如下代码:“确保这是一个Location,然后将第一个 int 绑定(bind)到名称 x ,第二个 int 命名为 y"

或者,您可以使用更详细的 match 语法:

let x = match loc with Location(x,y) -> x

对于您的特定情况,这有点矫枉过正,但对于不止一种情况的受歧视联合,match 是处理所有情况的唯一方法,例如:

type Position = 
   | Location of int*int
   | Unknown

let xOrZero = 
   match loc with
   | Location(x,y) -> x
   | Unknown -> 0

以上示例演示了模式 如何出现在let 绑定(bind)和match 表达式中,但这还不是全部。在 F# 中,几乎任何您认为是“变量声明”的东西实际上都是一种模式。只是大多数时候模式是微不足道的,如 let x = 5,但它们不一定是 - 例如设 x,y = 5,6

根据上面的推论,for elem in ... 中的 elem 也是一个模式。这意味着您可以就地解构元素:

for Location(x,y) in aShip.Projectiles do
    printfn "%d,%d" x y

或者,如果您想提取整个对,而不是单独提取 xy,这也是可能的:

for Location xy in aShip.Projectiles do
    printfn "%A" xy

关于f# - 如何在 F# 中更新 <T> 类型列表中的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44873209/

相关文章:

.net - F# 系统.TypeLoadException : The generic type 'System.Tuple` 3' was used with an invalid instantiation in assembly

php - 为什么我不能在 php mysql 中显示我的记录?

typescript - 何时使用可区分联合与实现接口(interface)的类

typescript - 将Typescript泛型中的类型限制为几种类型之一

.net - 那么,既然 F# 已经开源,那么它又是怎么回事呢?

exception - F# - 为什么 Seq.map 不传播异常?

list - 是否可以在 F# 中实现类似于 System.Linq.Enumerable.Cast 的 List.cast 函数?

Mysql 乘以相同记录的数量

python:如何将列添加到numpy中的记录数组

enums - 从枚举中读取而不进行模式匹配