Thomas
Thomas

Reputation: 12137

Can I extend a generic type? in F#

I have a DU representing error states:

type ExchangeError =
    | NoError
    | ServiceUnavailable
    | HttpError                 of HttpStatusCode * string
    ...

and I have one return type used everywhere:

Result<'a, ExchangeError>

Is there a way for me to add a method to that type that would work like this pseudo-solution:

type Result<'a, ExchangeError> with

    member this.GetOrFail
        match this with
        | Ok data -> data
        | Error e -> failwith $"error: {e}"

to be used like this:

let result = myData.GetOrFail

I find myself typing this over and over when doing exploration code and I don't care about handling errors, etc; I want either a result or stop at that point. So, I thought a helper method may be useful.

But how can this be achieved?

Upvotes: 2

Views: 72

Answers (2)

Brian Berns
Brian Berns

Reputation: 17153

There's nothing in GetOrFail that relies on the error type, so you can just make a generic extension:

type Result<'a, 'err> with

    member this.GetOrFail =
        match this with
        | Ok data -> data
        | Error e -> failwith $"error: {e}"

But if you really want this extension to apply only to Result<'a, ExchangeError>, you can do it with a C#-style extension member:

open System.Runtime.CompilerServices

[<Extension>]
type Extensions() =
    [<Extension>]
    static member GetOrFail (res : Result<'a, ExchangeError>) =
        match res with
        | Ok data -> data
        | Error e -> failwith $"error: {e}"

In this case, you have to invoke it as a method, rather than a property, but I figure that's still good enough.

Upvotes: 3

tranquillity
tranquillity

Reputation: 1685

I don't think you can add extension methods to a partially constrained generic type like that. Probably the best way is to just use a function:

module ExchangeError =

    let getOrFail (x: Result<'a, ExchangeError>) =
        match x with
        | Ok data -> data
        | Error e -> failwith $"error: {e}"

let result = getOrFail myData

Upvotes: 0

Related Questions