Why is the generic type mapped as obj in some expressions to the F # pattern?

I have the following code:

type Message<'a> = | Message of 'a

let handleMessage message =
    match box message with
    | :? Message<_> -> printfn "Message"
    | _ -> printfn "Not message"

let handleMessageEx message =
    match box message with
    | :? Message<int> -> printfn "Message"
    | _ -> printfn "Not message"

handleMessage <| Message 1
handleMessage <| Message (1 :> obj)
handleMessageEx <| Message 1

The output to F # Interactive is as follows:

Not message
Message 
Message

Why does the first statement result in "Not a message"? That is, when comparing a value enclosed in a square, F # cannot detect that it has the general type Message <_>, and if I do not specify the base type, it sets it to an object (therefore, it does not match (Message 1)).

+4
source share
2 answers

Whenever you see it _as a type parameter, think of it as a new type parameter that you are not interested in. If we pick up your first definition accordingly:

let handleMessage message =
    match box message with
    | :? Message<'_a> -> printfn "Message"
    | _ -> printfn "Not message"

:

warning FS0064: , , . '_a ' obj '.

, type - , , obj, , .

, , : fooobar.com/questions/580919/....

+4

, Message<_> , , , , generic type Message. , , obj. , generic - generic (, , Message) :

let handleMessage<'a> (message: obj) =
    match message with
    | :? Message<'a> -> printfn "Message"
    | _ -> printfn "Not message"

handleMessage <| Message 1       // Not message -> 'a inferred to be obj
handleMessage<int> <| Message 1  // Message -> 'a inferred to be int

, , , :

let handleMessage message =
    let typ = message.GetType()
    match typ with
    | _ when typ.GetGenericTypeDefinition() = typedefof<Message<_>> -> printfn "Message"
    | _ -> printfn "Not message"

handleMessage <| Message 1
handleMessage <| Message (1 :> obj)

.

+3

Source: https://habr.com/ru/post/1656811/


All Articles