1

i want to extend the option type with a join method and a contrained function.

type Option<'a> with 
    member this.join r =
        match r with
            | Some s -> 
                match s with
                    | Some really as r -> r
                    | _ -> None
            | _ -> None

Calling the method works fine as expected.

let x = None.join(Some (Some 1))

Now I want to define an overloaded function (inline and constraints as this is the only way in F#)

let inline join (t:^T) : ^U = (^T : (member join : ^T -> ^U) (t,t))

and call it like this

join (Some (Some 1))    

However now I get the error message

The type ''a option' does not support the operator 'join'
union case Option.Some: Value: 'T -> Option<'T>
The representation of "Value of type 'T"

which is strange insofar as I can write another type like this

type Result<'TSuccess, 'TError> = 
    | Success of 'TSuccess 
    | Error of 'TError list
    member this.join r =
        match r with
            | Success(s) -> 
                match s with
                    | Success(really) -> Success(really)
                    | Error(e) -> Error(e)
            | Error(e) -> Error e

and use it like this

join (Success (Success 1))

the difference being that in this case there is no extension method.

Any ideas anybody?

robkuz
  • 9,488
  • 5
  • 29
  • 50
  • 1
    Not really sure to understand the role of this `join` function. First the inner match is useless when `s` is `Some _` you return `s` otherwise (when `s` is `None`) you return `None`, just return `s`. Second you can simply rewrite `join` as `let join opt = Option.bind id opt`. Also why do you extend `Option<'T>` type instead of `Option` module ? – Sehnsucht Oct 07 '16 at 13:02
  • @Sehnsucht you are right the second match is not needed. thx for pointing that out. as for your second suggestion I explicitly created the inline function to remove the need to create separate fns for every type. In anyway this is closed as it is indeed a duplicate – robkuz Oct 07 '16 at 14:08
  • @robkuz FYI there is already a generic ``join`` in [FsControl](https://github.com/gmpl/FsControl/blob/a55d21b355c537960aaf0677be4bc36095a9c312/FsControl.Core/Operators.fs#L54) and it works with any monad, even if it doesn't have a ``Join`` method, as long as ``Bind``is properly defined. – Gus Oct 07 '16 at 15:23
  • @Gustavo I have downloaded it already and I am rewriting my stuff with yours. Where can I ask questions about it? – robkuz Oct 07 '16 at 17:49
  • @robkuz you can open issues there with questions. Otherwise you can contact me by email. I will send you an email to your github profile. – Gus Oct 08 '16 at 06:27

0 Answers0