f# - 如何使用 F# 制作同一记录的多个版本
问题描述
我有 3 个遵循类似模型的状态机:
- same states
- same calls for each state
只有这些调用的实现发生了变化。所有数据都包含在一个记录中,该记录还包含一个具有状态的 DU,并且还有一些其他常见参数。每个实现还将它们自己的字段添加到该记录中。
因此,我想弄清楚是否有一种方法可以制作我可以扩展的记录,但其中包含代码期望找到的许多常见字段。类似于类型接口的东西,但用于记录。
例如:
type State =
| a
| b
type StateMachine1StateObject =
{
State: State
SomeData: ...
}
type StateMachine2StateObject =
{
State: State
SomeOtherKindOfData: ...
}
我希望有一个状态机循环(这实际上是一个邮箱处理器循环)接收所有相同的消息,并且能够依赖于该类型中始终存在的某些字段,但记录本身可能不同因为它们包含自己的字段。
这怎么能结构化?看起来我不能使用带有记录的接口,也不能将多个记录合并为一个。
解决方案
如果您有很多共同的数据,则可以创建例如具有通用类型的字段的记录。
type State<'a> = {
Name: string
Id: int
Extended: 'a
}
type Person = {
FirstName: string
LastName: string
}
type Computer = {
CPU: string
Ghz: float
}
这样,您可以创建具有不同扩展数据的状态
// State<Person>
let x = {
Name = "foo"
Id = 1
Extended = {
FirstName = "David"
LastName = "Raab"
}
}
// State<Computer>
let y = {
Name = "bar"
Id = 2
Extended = {
CPU = "AMD"
Ghz = 3.6
}
}
您还可以从一条记录转换为另一条记录。您的状态机仅接受包含所需数据的记录。例如,您有一个只需要Name
和的状态机Id
。你创造。
type StateA = {
Name: string
Id: int
}
假设您现在使用共享密钥具有不同的状态。
type StateB = {
Name: string
Id: int
Extra: float
}
而不是类型hackery,泛型等,最简单的方法就是从B转换为A。
let stateBtoA (record:StateB) : StateA = {
Name = record.Name
Id = record.Id
}
所以你的状态机只接受StateA
,而且你有一堆函数,其他类型必须转换成StateA
才能传递给状态机。
如果由于某种原因您的状态机需要访问原始数据,您应该能够将其作为通用参数传递给函数调用。喜欢
message (x:StateA) (y:'a) : 'a =
// do something with x
y
message (stateBtoA data) data
因此,您的函数可以处理第一个参数,即 of StateA
,例如返回第二个参数y
,可能是StateB
。只要您的函数与y
. 它应该是通用的。
推荐阅读
- php - Laravel Eloquent - 按每种类型选择最大的 - join、max() 和 group by
- java - 如何在 MacOS 中确定 JRE 路径
- javascript - 从 React Js 中的数组列表获取输入字段
- javascript - 如何使用 JQuery 提取与模式匹配的子字符串
- google-maps - 在谷歌地图标记上添加一个弹出窗口
- python - 如果 Alembic 已经定义了架构,那么使用 sqlalchemy 定义的架构有什么关系?
- ios - 后台线程在主线程 ios swift 之前执行
- react-native - 更改存储状态后导航到初始路由
- java - 如何在 Java 中关闭和“销毁”对象是正确的
- bots - 如何在 kakao 通话频道中发送预定消息