What is the most idiomatic way of representing errors in F#

随声附和 提交于 2020-01-04 10:23:10

问题


I'm working on F# project and I wonder what is the best practice to return domain error using Result type in F#. There are several ways of doing it which I consider:

Inherited exceptions

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"))

Custom record type

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" })

Discriminated union of record type

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

So which way is more idiomatic and convenient to use? I also will be happy to see better options.


回答1:


Typically it would be a discriminated union. Every error requires different details to accompany the message. For instance:

type DomainErrorTypes =
| ItemNotFound of ItemId
| FileNotFound of string
| InvalidFormat of format
| IncompatibleItems of Item * Item
| SQLError of code:int * message:string
| ...

You can also capture some exceptions (not necessarily all):

| ...
| Exception of exn


来源:https://stackoverflow.com/questions/53650500/what-is-the-most-idiomatic-way-of-representing-errors-in-f

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!