首页 > 解决方案 > 受歧视工会内部的分配

问题描述

我是 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#discriminated-union

解决方案


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

1是一个类型的值int

(1, 1)是一个类型的值(int * int)

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

type DUType =
| DUCase1 of int

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


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


因此,在您的代码中,您不能说 DU 案例必须始终包含某个。您需要编写一个函数,而不是采用 aDirection并返回 a 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 种“模式”:

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

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


推荐阅读