gpt4 book ai didi

f# - 是否有可能让 F# 能够识别 DU 的重叠并使用正确的本身?

转载 作者:行者123 更新时间:2023-12-05 09:28:36 24 4
gpt4 key购买 nike

type GenericResult =
| Ok
| Error of string

type LoginResult =
| Ok
| UserNotFound
| WrongPassword

let check something:GenericResult =
match something with
//| true -> Ok // error:This expression was expected to be of type "GenericREsult" but here has type "LoginResult"
| true -> GenericResult.Ok // I'm forced to specify GenericResult.Ok
| false -> Error "aargg!"

let checkLogin something:LoginResult =
match something with
| true -> Ok // here I don't need to specify the DU because this is defined after
| _ -> WrongPassword

我想在这两种方法中只使用“Ok”,而不需要指定 DU。
我看到如果值发生冲突,最后一个是“预定义”。

理想情况下,我希望有一种继承
在另一个 DU 中重用 DU 的一部分。
例如:

type GenericResult =
| Ok
| Error of string

type LoginResult =
//| GenericResult.Ok
| UserNotFound
| WrongPassword

type SaveResult =
| Created
| Updated
//| GenericResult.Error


let checkLogin something: LoginResult | GenericResult.Ok =
match something with
| true -> Ok
| _ -> WrongPassword

[编辑]我觉得需要此功能的真实场景是来自 3 个不同逻辑类的 3 个不同结果。
future 会有更多的案例,因此重复的 DU 值的乘法将会增加。

// DUs ordered from the most specific to the most generic

type BalanceUpdateResult =
| Created
| Updated
| InvalidRequest of string

type DeleteResult =
| Ok
| InvalidRequest of string

type Result<'T> =
| Ok of 'T
| NotValid of string
| Error of string

目标是在消费者中使用干净的匹配语法,例如,DU 的值最终将用于引发异常或返回创建的值。

// balance update function (result is BalanceUpdateResult):
match result with
| Created -> this.createOkWithStatus 201
| Updated -> this.createOkWithStatus 200
| InvalidRequest error -> this.createErrorForConflict error

// company creation function (result is Result<Company>):
match result with
| Result.Ok newItem ->
context.Logger.Log $"Company created. New Id:{newItem.Id}, Name:{newItem.Name}."
this.createCreated newItem
| NotValid error -> base.createErrorForConflict error
| Error error -> base.createError error

这里以第二种情况为例,InvalidRequest不被接受,因为它属于错误的DU。
必须在各处指定 DU 会导致一团糟,如下例所示(请参阅许多 Result<_>。):

    interface ICompanyLogic with
member this.Create(company:Company):Result<Company> =
match normalize company |> validate with
| NotValid msg -> Result<_>.NotValid msg
| Valid validCompany ->
match companyRepository.Exists(validCompany.Name) with
| true -> Result<_>.NotValid($"A company with name \"{validCompany.Name}\" already exists.")
| _ ->
let newCompany = assignNewId validCompany
companyRepository.Create(newCompany)
Result<_>.Ok(newCompany)

member this.Update (company:Company):Result<Company> =
let checkNameExists company =
match companyRepository.GetByName company.Name with
| Some c when c.Id <> company.Id -> NotValid $"A company with name \"{company.Name}\" already exists."
| _ -> Valid company

match normalize company |> validate with
| NotValid msg -> Result<_>.NotValid msg
| Valid c -> match checkNameExists c with
| Valid c -> companyRepository.Update c; Result<_>.Ok c
| NotValid msg -> Result<_>.NotValid msg

最佳答案

我认为实现您正在尝试做的事情的最佳方法是从具有表示错误类型的类型参数的通用 Result 类型开始:

type Result<'TError> =
| Ok
| Error of 'TError

这允许您使用不同的类型来表示错误,包括 string,还有另一个 DU 来捕获更具体的错误类型。然后,您可以将 GenericResultLoginResult 定义为两个类型别名:

type LoginError =
| UserNotFound
| WrongPassword

type GenericResult = Result<string>
type LoginResult = Result<LoginError>

要报告登录错误,您现在可以使用 Error WrongPassword 将特定错误包装在通用 Error 构造函数中。您的两个函数的实现如下所示:

let check something:GenericResult =
match something with
| true -> Ok
| false -> Error "aargg!"

let checkLogin something:LoginResult =
match something with
| true -> Ok
| _ -> Error WrongPassword

关于f# - 是否有可能让 F# 能够识别 DU 的重叠并使用正确的本身?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71257330/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com