如何对描述自身成员之间关系的代数数据类型进行建模,除非它是自相关的?

问题描述

我正在学习代数数据类型(最近),以及如何使用它们来防止不可表示的类型。

我需要对两个方向(北、东、南、西)之间的关系进行建模。

所有组合都有效,除非它与自身组合。

+-------+-------+---------+
| Left  | Right | Valid   |
+-------+-------+---------+
| North | North | Invalid |
| North | East  | Valid   |
| North | South | Valid   |
| North | West  | Valid   |
+-------+-------+---------+
| East  | North | Valid   |
| East  | East  | Invalid |
| East  | South | Valid   |
| East  | West  | Valid   |
+-------+-------+---------+
| South | North | Valid   |
| South | East  | Valid   |
| South | South | Invalid |
| South | West  | Valid   |
+-------+-------+---------+
| West  | North | Valid   |
| West  | East  | Valid   |
| West  | South | Valid   |
| West  | West  | Invalid |
+-------+-------+---------+

据我所知,我们或许可以通过查看代数来构建类型系统。这里总共有 16 种组合和 12 种有效组合(4 * 44 * 3)。由于有 4 个方向,这似乎意味着需要另一种只有 3 个值的类型。

这似乎是一种产品类型。组合的数量是乘法的结果。

通过一些心理体操,我想出了一些似乎有效但很难阅读的东西。

sealed interface Direction

sealed interface NotNorth
sealed interface NotEast
sealed interface NotSouth
sealed interface NotWest

object North : Direction,NotEast,NotSouth,NotWest
object East : Direction,NotNorth,NotWest
object South : Direction,NotWest
object West : Direction,NotSouth

typealias EntranceFromNorth = Pair<North,NotNorth>
typealias EntranceFromEast = Pair<East,NotEast>
typealias EntranceFromSouth = Pair<South,NotSouth>
typealias EntranceFromWest = Pair<West,NotWest>

//val NorthNorth = EntranceFromNorth(North,North)// compilation error
val NorthEast = EntranceFromNorth(North,East)
val NorthSouth = EntranceFromNorth(North,South)
val NorthWest = EntranceFromNorth(North,West)

val EastNorth = EntranceFromEast(East,North)
//val EastEast = EntranceFromEast(East,East)// compilation error
val EastSouth = EntranceFromEast(East,South)
val EastWest = EntranceFromEast(East,West)

val SouthNorth = EntranceFromSouth(South,North)
val SouthEast = EntranceFromSouth(South,East)
//val SouthSouth = EntranceFromSouth(South,South)// compilation error
val SouthWest = EntranceFromSouth(South,West)

val WestNorth = EntranceFromWest(West,North)
val WestEast = EntranceFromWest(West,East)
val WestSouth = EntranceFromWest(West,South)
//val WestWest = EntranceFromWest(West,West)// compilation error

有没有更好的方法可以模拟这种与类型系统的关系?

让我觉得尴尬的部分是

  • 多种 Not* 类型。感觉类型应该是包容性的,而不是排斥性的,但我不确定如何构建一个包容性类型来对此建模。
  • 我不确定这是否真的代表 ADT,因为我最近才知道它的存在。
  • 我想知道是否最好有一个显式的 Invalid 类型,这样就不会混淆 Invalid 类型是否存在,或者它是否被错误地省略(将解决方案更改为具有 16 种可能的状态,而不是 12 种)。

解决方法

这些方向代表通过房间的入口和出口点。这是一种单向遍历,向后是他们进入房间的地方。

在这种情况下,与其将出口建模为绝对主要方向,您还可以将其建模为入口方向的相对方向之一,无论是在左侧、右侧还是在前面。退出方向不包括“向后”,所以你不能从你来的地方退出。

sealed interface EntranceDirection
sealed interface ExitDirection

object North : EntranceDirection
object East : EntranceDirection
object South : EntranceDirection
object West : EntranceDirection

object Left : ExitDirection
object Right : ExitDirection
object Front : ExitDirection

typealias RoomTraversalSegment = Pair<EntranceDirection,ExitDirection>

实际上,两个枚举也可以完成这项工作:

enum class EntranceDirection {
    NORTH,SOUTH,EAST,WEST
}

enum class ExitDirection {
    LEFT,RIGHT,FRONT
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...