7
votes

Is there any way to pattern match on discriminated union functions, e.g.:-

type Test =
  | A of string
  | B of int
  | C of char

let DefaultTest t =
  match t with
  | A(_) -> A(null)
  | B(_) -> B(0)
  | C(_) -> C('\u0000')

let a = A |> DefaultTest

Obviously this code isn't valid F# as DefaultTest accepts one parameter of type Test rather than 'a -> Test. Is there any way of achieving this without specifying a value for the discriminated union?

What I'm after, ultimately, is a function which inputs a function of type 'a -> Test and outputs Test(default value of 'a).

3

3 Answers

5
votes

I am not clear what you are after, but does this help?

type Foo =
    | A of int
    | B of string

let CallWithDefault f =
    let x = Unchecked.defaultof<_>
    f x

let defaultA = CallWithDefault A    
let defaultB = CallWithDefault B    
printfn "(%A) (%A)" defaultA defaultB 
3
votes

Not sure what you're after but something like:

let DefaultTest (t :obj) =
  match t with
  | :? (string->Test) as a -> Some (a null)
  | :? (int -> Test) as b -> Some (b 0)
  | :? (char -> Test) as c -> Some (c '\u0000')
  | _ -> Option.None

might work for you...

1
votes

This could possibly work when all the constructors had the same argument type, say int. Then one could

match t 0 of
| A 0 -> ...
| B 0 -> ...