f# - 受歧视工会内部的分配

标签 f# discriminated-union

我是 F# 新手,正在尝试开发贪吃蛇游戏,如果这听起来很愚蠢,请原谅我。

目前,这是游戏的模型:

// value objects
type Position = int * int
type Block = { Position: Position }
type Tail = { Blocks: Block list }
type Direction = 
  | North  
  | South  
  | West  
  | East 
//
 
// entities
type Snake = { Tail: Tail }
type World = { Snake: Snake }
//

为了让移动蛇时变得更简单,我想要每个 Direction拥有自己的Position ,就像:

type Direction = 
  | North of Position (0, 1)
  | South of Position (0, -1)
  | West of Position (-1, 0)
  | East of Position (0, 1)

所以我可以在这里应用它:

let moveSnakeHead direction snake =
  // easily move the snake's head
  // tail[0].x += direction.x, tail[0].y += direction.y

但是,在我看来这是不可能的of Position (x, y)在受歧视的工会内部?

有人能解释一下为什么吗?我正在尽力学习类型。还有什么替代方案?

最佳答案

确保您清楚 F# 中类型之间的区别。对于刚接触 F# 的人来说,这是一个常见的陷阱,尤其是在受歧视的工会方面。

1int 类型的值。

(1, 1)(int * int) 类型的值。

当您定义 DU 类型时,每个 case 都可以保存某种类型的数据:

type DUType =
| DUCase1 of int

因此,每个 DU 案例可以包含任何 int,而不仅仅是特定的 int


您的代码中还有一个类型别名:type Position = int * int。这只是说你可以在任何地方写 Position ,它的含义与 int * int 相同。它实际上不是另一种类型。


因此,在您的代码中,您不能说 DU 案例必须始终包含特定的。您需要编写一个函数,该函数接受 Direction 并返回 Position:

type Direction = 
  | North  
  | South  
  | West  
  | East 

let directionToPostion direction : Position = 
    match direction with
    | North -> (0, 1)
    | South -> (0, -1)
    | West -> (-1, 0)
    | East -> (0, 1)

您编写的任何 F# 代码通常始终处于 3 种“模式”:

  • 值(value)
  • 类型
  • 模式(如模式匹配)

尝试确保您在任何给定时间都知道自己属于这三者中的哪一个。

关于f# - 受歧视工会内部的分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64735519/

相关文章:

typescript 与联合的交集会导致不存在的属性

f# - 受歧视的工会可以相互引用吗?

f# - 如何使用FsUnit检查歧视工会的情况?

c# - 您可以在一个项目中混合使用 .net 语言吗?

f# - 避免使用 "mutable"变量来调用带有 byref(C# 中的 out)参数的方法?

f# - 删除 F# 列表中的第三个元素

typescript - 通过添加新类型对可区分的联合进行类型检查

f# - 为什么 F# 歧视联合无法使其 TypeConverter 受到 JSON.NET 的尊重,而其他类型却可以?

unit-testing - 在 F# 单元测试中检查函数相等性

F#:为什么使用外部函数版本比将函数作为参数传递更快