在F#中表示错误的最惯用方法是什么?

nep*_*nao 2 error-handling f#

我正在研究F#项目,我想知道使用ResultF#中的类型返回域错误的最佳做法是什么.我认为有几种方法可以做到:

继承的异常

type DomainException(message) =
    inherit Exception(message)

type ItemNotFoundException(item) =
    inherit DomainException(sprintf "Item %s is not found" item)

let findItem item =
    match item with
    | Some x -> Ok x
    | None -> Error(new ItemNotFoundException("someitem"))
Run Code Online (Sandbox Code Playgroud)

自定义记录类型

type DomainError =
    { Name : string
      Message : string }

let findItem item =
    match item with
    | Some x -> Ok x
    | None ->
        Error({ Name = "ItemNotFound"
                Message = "Item someitem is not found" })
Run Code Online (Sandbox Code Playgroud)

区分记录类型的联合

type DomainErrorTypes =
    | ItemNotFoundError of DomainError
    | ItemInvalidFormat of DomainError

let findItem item =
    match item with
    | Some x -> Ok x
    | None ->
        { Name = "ItemNotFound"
          Message = "Item someitem is not found" }
        |> ItemNotFoundError
        |> Error
Run Code Online (Sandbox Code Playgroud)

那么哪种方式比较惯用且使用方便?我也很乐意看到更好的选择.

AMi*_*res 5

通常情况下,这将是一个有区别的联盟.每个错误都需要不同的细节来配合消息.例如:

type DomainErrorTypes =
| ItemNotFound of ItemId
| FileNotFound of string
| InvalidFormat of format
| IncompatibleItems of Item * Item
| SQLError of code:int * message:string
| ...
Run Code Online (Sandbox Code Playgroud)

您还可以捕获一些异常(不一定全部):

| ...
| Exception of exn
Run Code Online (Sandbox Code Playgroud)