开发者

Constraint Mismatch Error when Matching on Data Type

I am trying to process the contents of a dictionary based on the type of contained element (String, Int, Datetime etc). The following is a small test snippet which loads some test data and then extracts by type.

However I get the following constraint mismatch error which I don't understand - any ideas?

Error Info:

unmapdict.fsx(29,23): error FS0193: Type constraint mismatch.

The type 'String' is not compatible with the type 'Type'

open System
open System.Collections.Generic

// Type for dict entries
type dStruct =  {
   ftype: Type; 
   fvalue:obj;
}

let main() =
    printfn "\n>>>>>> Extract Dictionary Elements  <<<<< \n" 
    let ddict = new Dictionary<string, dStruct>()
    let str = "String Data"
    let rstring =  { ftype=str.GetType(); fvalue=str ;}
    ddict.Add("String", rstring)
    let intn = 999
    let rint32 =  { ftype=intn.开发者_StackOverflowGetType(); fvalue=intn ;}
    ddict.Add("Int32", rint32)

    let rdatetime =  {ftype=System.DateTime.Now.GetType(); fvalue=System.DateTime.Now}
    ddict.Add("DateTime", rdatetime)

    // Extract dict value elements; emumerate data types
    ddict
        |> Seq.map ( fun (KeyValue(k,v)) -> v)
        |> Seq.iter (fun v ->  
                    // Error occurs here >>
                    match v.ftype with 
                    | :?System.String -> printfn "String Found ";
                    | :?System.Int32 -> printfn "Integer Found ";
                    | :?System.DateTime -> printfn "DateTime Found ";
                    |_ -> printfn "Unmatched Element"
                    // printfn "Dict: ftype: %A; fvalue: %A" v.ftype v.fvalue
                    )

    printfn "\n>>>>>> F# Done  <<<<< \n" 

main()


Since .NET objects carry their types with them, I don't see any point to the dStruct type (which is misleadingly named anyway, since it's not a struct). On a related note, your type test patterns (:? string, etc.) don't work because you're testing an instance of class Type against them, when you should be testing the instance that you actually care about. That is:

let main() =
    printfn "\n>>>>>> Extract Dictionary Elements  <<<<< \n" 
    let ddict = new Dictionary<string, obj>()
    let str = "String Data"
    ddict.Add("String", str)
    let intn = 999
    ddict.Add("Int32", intn)

    ddict.Add("DateTime", System.DateTime.Now)

    // Extract dict value elements; emumerate data types
    ddict
        |> Seq.map ( fun (KeyValue(k,v)) -> v)
        |> Seq.iter (fun v ->  
                    match v with 
                    | :?System.String as s -> printfn "String Found: %s" s;
                    | :?System.Int32 as i -> printfn "Integer Found: %i" i;
                    | :?System.DateTime as dt -> printfn "DateTime Found: %A" dt;
                    |_ -> printfn "Unmatched Element"
                    )

    printfn "\n>>>>>> F# Done  <<<<< \n" 

main()


A .NET Type as returned by GetType is not the same as a class. Instead, it is an instance of class Type. Also, Type cannot be used in pattern matching (unless we define special active patterns), but we can compare for equality.

If you change your code like this, it will work:

               if v.ftype  = typeof<String> then printfn "String Found "
               elif v.ftype = typeof<System.Int32> then printfn "Integer Found "
               elif v.ftype = typeof<System.DateTime> then printfn "DateTime Found "
               else printfn "Unmatched Element"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜