f# - 用于返回具有不同结构的匿名记录的有效 F# 函数
问题描述
我正在编写一个 F# 库来调用 HTTP REST API。HTTP 请求的 JSON 正文根据请求应发回的信息量或信息类型而有所不同。
例如,下面是使用匿名记录创建 json 主体的代码,用于 HTTP 请求以列出项目中的文件,https://documentation.dnanexus.com/developer/api/search#api-method-system-查找数据对象。
type Request = {
ApiToken: ApiToken
ProjectId: ProjectId
StartingAt: ObjectId option
}
module Request =
let toJson request =
let (ProjectId projectId) = request.ProjectId
let baseJson = {| scope = {| project = projectId
recurse = true |}
describe = true |}
match request.StartingAt with
| Some (ObjectId objectId) ->
{| baseJson with starting = {| project = projectId
id = objectId |} |}
| None ->
baseJson
此代码无法编译。相反,在此示例的最后一行中,编译器会引发以下错误:
This anonymous record does not have enough fields. Add the missing fields [starting].F# Compiler(1)
是否可以编写一个返回具有不同结构的匿名记录的函数?
解决方案
这不是匿名记录本身的问题 - 没有明确的返回类型toJson
- 根据分支,您返回不同的类型。
你有几个选择:
starting
创建一个对象,可以在 None 分支上将其设置为 null :
match request.StartingAt with
| Some (ObjectId objectId) ->
{| baseJson with starting = box {| project = projectId
id = objectId |} |}
| None ->
{| baseJson with starting = null |}
- 在此函数中执行 json 序列化:
match request.StartingAt with
| Some (ObjectId objectId) ->
serialize
{| baseJson with starting = {| project = projectId
id = objectId |} |}
| None ->
serialize baseJson
其中 serialize 是一个函数,它接受任何 'T 并返回一个字符串。
- 最后一种选择是用一个有区别的联合来统一这两个分支。但是,在这种情况下,我认为这不值得,因为无论如何您都在序列化此记录。
主要的是 match 表达式的两个“分支”都必须返回相同的类型。这对于 F# 中的任何分支表达式都是相同的,例如 match 或 if / else。它适用于所有类型——原语、记录、元组、联合等。
推荐阅读
- linux-containers - Podman 如果有很多容器,如何删除所有退出的容器
- c# - 为什么我不能使用此 ForEach 循环将整数分配给数组(抛出“未设置对象引用”异常)
- flutter - 读取继承自 stateNotifier 的类中的状态
- python - 合并两个排序的python列表
- javascript - 如果使用Angular为空日期选择器,如何禁用按钮
- c++ - 如何将函数调用与回调同步?
- sql - 使用SQL将数据从阿拉伯语翻译成英语,数据库是oracle
- google-api - 无法在 Google Calendar API 中获取我拥有的列表
- spring-boot - 使用 springboot_springdata_JPA 生成动态查询时面临问题。未生成所需的查询
- python - 堆叠列