给定一个受歧视的工会案例,你能得到下一个案例吗?
Given a discriminated union case, can you get the next case?
我正在尝试为机器人模拟编写代码。对于方向,我有一个DU:
type Direction = North | East | South | West
当类型为South
时,你给出向右转两次的指令,是否有一个选项让值实际上再次从North
开始?
你所拥有的是一个定义了 4 个案例的可区分联合。没有自动理解旋转值的方法,但您可以编写自己的函数来实现此目的:
type Direction = North | East | South | West
module Direction =
let turnRight =
function //The function keyword is a shortcut for (fun x -> match x with...)
| North -> East
| East -> South
| South -> West
| West -> North
//Usage
let direction = North
let direction2 = Direction.turnRight direction
注意:在 F# 中,通常在同名模块中声明作用于特定类型的函数。
有一种方法可以使用反射自动获取下一个案例。通常最好尽可能避免反射,但是它的这种用法非常受限,因为它只在您加载模块时运行一次,所以如果它导致异常应该很容易立即发现:
open FSharp.Reflection
let inline getUnionCases<'a> () =
FSharpType.GetUnionCases typeof<'a>
|> Array.map (fun case ->
FSharpValue.MakeUnion(case,[||]) :?> 'a)
type Direction = North | East | South | West
let directions = getUnionCases<Direction>()
let rightDirections =
directions
|> Array.mapi (fun i d -> d, directions.[(i + 1) % directions.Length])
|> Map
let turnRight d = rightDirections |> Map.find d
North |> turnRight // East
West |> turnRight // North
反射发生在计算模块级别值 directions
时,因此它在模块加载时发生一次(即应用程序启动)。如果将此值放在函数或 class 中,那么您将失去这种安全性。
只有 inline
关键字才能在 Fable(F# 到 JS 编译器)中工作
这仅适用于每个 DU 案例都没有数据的情况。如果您将 North
更改为 North of int
,此代码将引发异常。
我正在尝试为机器人模拟编写代码。对于方向,我有一个DU:
type Direction = North | East | South | West
当类型为South
时,你给出向右转两次的指令,是否有一个选项让值实际上再次从North
开始?
你所拥有的是一个定义了 4 个案例的可区分联合。没有自动理解旋转值的方法,但您可以编写自己的函数来实现此目的:
type Direction = North | East | South | West
module Direction =
let turnRight =
function //The function keyword is a shortcut for (fun x -> match x with...)
| North -> East
| East -> South
| South -> West
| West -> North
//Usage
let direction = North
let direction2 = Direction.turnRight direction
注意:在 F# 中,通常在同名模块中声明作用于特定类型的函数。
有一种方法可以使用反射自动获取下一个案例。通常最好尽可能避免反射,但是它的这种用法非常受限,因为它只在您加载模块时运行一次,所以如果它导致异常应该很容易立即发现:
open FSharp.Reflection
let inline getUnionCases<'a> () =
FSharpType.GetUnionCases typeof<'a>
|> Array.map (fun case ->
FSharpValue.MakeUnion(case,[||]) :?> 'a)
type Direction = North | East | South | West
let directions = getUnionCases<Direction>()
let rightDirections =
directions
|> Array.mapi (fun i d -> d, directions.[(i + 1) % directions.Length])
|> Map
let turnRight d = rightDirections |> Map.find d
North |> turnRight // East
West |> turnRight // North
反射发生在计算模块级别值
directions
时,因此它在模块加载时发生一次(即应用程序启动)。如果将此值放在函数或 class 中,那么您将失去这种安全性。只有
inline
关键字才能在 Fable(F# 到 JS 编译器)中工作这仅适用于每个 DU 案例都没有数据的情况。如果您将
North
更改为North of int
,此代码将引发异常。