Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Discriminated union method doesn't see its static member

The problem seems to be dumb, but I really don't get it.

module Responses =
    type Failure = 
        | Problem of string 
        | Error of exn 
        | Timeout
        static member toString x = 
            match x with
            | Problem str -> sprintf "Problem %s" str
            | Error e -> sprintf "Error %s" (e.ToString())
            | Timeout -> "Timeout"
        override x.ToString() = Failure.toString x 

error is

      override x.ToString() = Failure.toString x;;
--------------------------------------^^^^^^^^
stdin(11,41): error FS0039: The field, constructor or member 'toString' is not defined

Reason is that f# for some reason thinks that Failure is of type Microsoft.FSharp.Core.Operations.Failure

When I try to write

override x.ToString() = Responses.Failure.toString x

I get

Startup.fs(14,33): error FS0039: The namespace or module 'Responses' is not defined

When I rename Failure to for example xFailure, it works. But I really do not want to rename it. Can I somehow avoid renaming and use static method?

like image 479
Rustam Avatar asked Feb 14 '23 04:02

Rustam


1 Answers

This is a bit surprising behavior! I think it is happening because Failure is another type that is defined in the F# core library. When you try calling the static method, the compiler (for some reason) picks only the F# library type, but does not union the static methods (which is what I would expect).

I think it might be a bug - so please report it on the F# CodePlex site.

As a workaround, I only came up with a fairly ugly idea, which is to define a private type alias such as FailureStatic and then use the alias to call static members (the users of your library will not see it).

module Responses =
    type private FailureStatic = Failure
    and Failure = 
        | Problem of string 
        | Error of exn 
        | Timeout
        static member toString x = 
            match x with
            | Problem str -> sprintf "Problem %s" str
            | Error e -> sprintf "Error %s" (e.ToString())
            | Timeout -> "Timeout"
        override x.ToString() = FailureStatic.toString x 
like image 199
Tomas Petricek Avatar answered Feb 16 '23 01:02

Tomas Petricek