MiloDC
MiloDC

Reputation: 2415

F#: How do I pattern match a type value?

I have a function that takes a generic parameter, and inside it I need to execute one of two functions depending on the type of the parameter.

member this.Load<'T> _path =
    let hhType = typeof<HooHah>
    match typeof<'T> with
        | hhType -> this.LoadLikeCrazy<'T> _path
        | _ -> this.LoadWithPizzaz<'T> _path

.... where LoadLikeCrazy and LoadWithPizzaz both return a 'T.

VS informs me that the wildcard case will never get executed, since I am apparently getting the type of a generic at compile time, and not the actual type at runtime. How do I go about this?

Upvotes: 9

Views: 2327

Answers (3)

Ankur
Ankur

Reputation: 33637

What nyinyithann has mentioned is correct. I wrote the below code in F#

let Hello name = 
let n = "Sample"
match name with
| n -> 1
| _ -> 0

Got the same warning. Used reflector to see what code is generate and found the below code (decompiled in C#)

public static int Hello<a>(a name)
{
  a local = name;
  a name = local;
  return 1;
}

Not sure why compiler did this :( . Can anyone describe this behaviour ?

Upvotes: 0

Nyi Nyi
Nyi Nyi

Reputation: 788

In your code , the first pattern match rule doesn't compare typeof<'T> against hhType. Instead, it will introduce a new value called hhType. That's the reason you got warning. I'd rather modify the code like this.

member this.Load<'T> _path =        
    match typeof<'T> with        
    | x when x = typeof<HooHah>  -> this.LoadLikeCrazy<'T> _path        
    | _ -> this.LoadWithPizzaz<'T> _path

Upvotes: 13

Daniel
Daniel

Reputation: 47904

Is _path an instance of 'T? If so, Talljoe's solution will work, otherwise you'll have to do something like:

member this.Load<'T> _path =
    if typeof<'T> = typeof<HooHah> then this.LoadLikeCrazy<'T> _path
    else this.LoadWithPizzaz<'T> _path

The reason for the error is that hhType within your match expression is shadowing the prior declaration of hhType. So, it's merely capturing the value of your match expression into a new binding. This matches everything, therefore your wildcard condition will never be hit.

Upvotes: 2

Related Questions