How do I Override ToString in a Composite Type in F#?
Asked Answered
K

1

10

I'm learning about creating composite* types in F# and I ran into a problem. I have this type and a ToString override.

type MyType =
    | Bool of bool
    | Int of int
    | Str of string
    with override this.ToString() =
            match this with
            | Bool -> if this then "I'm True" else "I'm False"
            | Int -> base.ToString()
            | Str -> this

let c = Bool(false)
printfn "%A" c

I get an error inside the ToString override that says "This constructor is applied to 0 argument(s) but expects 1". I was pretty sure this code wouldn't compile, but it shows what I'm trying to do. When I comment out the override and run the code, c is printed out as "val c : MyType = Bool false". When I step into that code, I see that c has a property Item set to the boolean false. I can't seem to access this property in the code however. Not even if I annotate c.

How should I be overriding ToString in this situation?

* I'm pretty sure these are called composite types.

Kid answered 8/12, 2014 at 15:51 Comment(0)
E
15

When you are using a Discriminated Union (DU) (that's the appropriate name for that type), you need to unpack the value in the match statement like this:

type MyType =
    | Bool of bool
    | Int of int
    | Str of string
    with override this.ToString() =
            match this with
            | Bool(b) -> if b then "I'm True" else "I'm False"
            | Int(i) -> i.ToString()
            | Str(s) -> s

let c = Bool(false)
printfn "%A" c

The Item property that you're seeing is an implementation detail and is not intended to be accessed from F# code. Merely using this doesn't work because the DU is a wrapper around the value, so this refers to the wrapper, not to the contained value.

Escorial answered 8/12, 2014 at 16:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.