f# - 有没有一种简单的方法来继承计算表达式的行为?
问题描述
您将如何构建一个新的计算表达式来继承现有的大多数行为,但您可能需要覆盖某些行为?
语境:
从现在开始,我将使用 CE 作为计算表达式的缩写。
我正在使用https://github.com/demystifyfp/FsToolkit.ErrorHandling
我有一个“分层”应用程序,它有一个从数据库层获取的存储库。
到目前为止,数据库层中的所有函数都Task<Result<'T, DatabaseError>>
通过taskResult { ... }
CE 从FsToolkit.ErrorHandling
.
但是在存储库中,我总是想返回Task<Result<'T, RepositoryError>>
,RepositoryError
可以很容易地从中派生DatabaseError
,这意味着我的大部分代码看起来像这样:
let getAll con offset chunk = taskResult {
let! products =
ProductEntity.allPaginated offset chunk con
|> TaskResult.mapError RepositoryError.fromDatabaseError
let! totalCount =
ProductEntity.countAll con
|> TaskResult.mapError RepositoryError.fromDatabaseError
return { Items = products; TotalCount = totalCount }
}
目标:
- 我希望
TaskResult.mapError RepositoryError.fromDatabaseError
在新的 CE 内部进行所有这些调用。让我们称之为repoTaskResult { ... }
- 我需要拥有原始
taskResult { ... }
CE的所有当前功能
let getAll con offset chunk = repoTaskResult {
let! products = ProductEntity.allPaginated offset chunk con
let! totalCount = ProductEntity.countAll con
return { Items = products; TotalCount = totalCount }
}
编辑:
A. 尝试通过继承解决它(但推断正确的类型不起作用)
type RepositoryTaskResultBuilder() =
inherit TaskResultBuilder()
member __.Bind(databaseTaskResult: Task<Result<'T, DatabaseError>>, binder) =
let repoTaskResult = databaseTaskResult |> TaskResult.mapError RepositoryError.fromDatabaseError
__.Bind(taskResult = repoTaskResult, binder = binder)
let repoTaskResult = RepositoryTaskResultBuilder()
用法:
let getAll con offset chunk = repoTaskResult {
let! other = Task.singleton 1
let! products = ProductEntity.allPaginated offset chunk con
let! totalCount = ProductEntity.countAll con
return { Items = products; TotalCount = totalCount }
}
继承版本的结论:
目标 #2 很容易实现,other
正确推断为 int。如果没有任何类型推断的帮助,目标 #1 是无法实现的。默认让!似乎被推断为底层TaskResultBuilder的更通用的Bind方法之一。这意味着整个返回类型被推断为 Task<Result<'T, DatabaseError>>。
如果您希望通过将 return 语句替换为 来帮助进行类型推断return! Result<_,RepositoryError>.Ok { Items = products; TotalCount = totalCount }
,那么您就可以开始了,就像现在 let!之前的语句正确地使用了新实现的 Bind 方法。
解决方案
推荐阅读
- javascript - 自动从 gmail 帐户垃圾邮件文件夹中删除包含特定关键字的电子邮件
- javascript - 当文件在 XAMPP 中时,console.log 不起作用 onclick 事件
- robotics - 在 Drake 工具箱的 IK 解算器选项中设置详细程度时如何设置 SolverId?
- media - 具有相同权限的 Google 驱动器音频文件,但只有一个可以访问,其他的会抛出 403(禁止访问)错误
- r - 将列表的元素提取为 r 中自定义函数中的单个参数
- julia - 如何思考 Julia 中的“开始”块
- web-applications - 创建制作自定义电子表格的网络应用程序的方法?
- r - 有没有办法在 R 中为海报添加情节
- python - 无法以正确格式为 Python 中的 sql 查询声明日期变量
- sql - Django ORM左连接到同一张表