如何从obj向下转换到选项< obj&gt ;? [英] How to downcast from obj to option<obj>?

查看:184
本文介绍了如何从obj向下转换到选项< obj&gt ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,它接受一个类型为对象的参数,需要将其下转换为选项< obj>

I have a function that takes a parameter of type object and needs to downcast it to an option<obj>.

member s.Bind(x : obj, rest) =
    let x = x :?> Option<obj>

如果我传递(例如) Option< string> as x ,最后一行抛出异常:无法转换类型为Microsoft.FSharp.Core.FSharpOption'1的对象[System.String ]'键入'Microsoft.FSharp.Core.FSharpOption'1 [System.Object]'。

If I pass (for example) an Option<string> as x, the last line throws the exception: Unable to cast object of type 'Microsoft.FSharp.Core.FSharpOption'1[System.String]' to type 'Microsoft.FSharp.Core.FSharpOption'1[System.Object]'.

或者,如果我尝试类型测试: / p>

Or, if I try a type test:

member s.Bind(x : obj, rest) =
   match x with
    | :? option<obj> as x1 -> ... // Do stuff with x1
    | _ -> failwith "Invalid type"

然后 x never匹配选项< obj>

then x never matches option<obj>.

为了使这项工作,我目前必须指定类型选项包含(例如,如果函数传递一个选项< string> ,我将参数下拉到而不是选项< obj> ,函数工作。

In order to make this work, I currently have to specify the type the option contains (e.g. if the function is passed an option<string>, and I downcast the parameter to that rather than option<obj>, the function works.

有一种方法我可以将参数下调到 option< obj> 我试过了选项< _> 选项<#obj> 选项<'a> 的结果相同。

Is there a way I can downcast the parameter to option<obj> without specifying what type the option contains? I've tried option<_>, option<#obj>, and option<'a> with the same results.

obj 因为我为monad编写了一个接口,所以Bind需要根据实现接口的monad绑定不同类型的值,这个特殊的monad是一个连续的monad ,所以它只是想确保参数 Some(x)而不是,然后传递 x 打开休息。 (我需要这个接口的原因是因为我在写一个monad转换器,我需要一个方法告诉它的参数monads实现绑定和返回。)

By way of background, the parameter needs to be of type obj because I'm writing an interface for a monad, so Bind needs to bind values of different types depending on the monad that implements the interface. This particular monad is a continuation monad, so it just wants to make sure the parameter is Some(x) and not None, then pass x on to rest. (The reason I need the interface is because I'm writing a monad transformer and I need a way to tell it that its parameter monads implement bind and return.)

strong> Update:我设法通过在它成为这个函数的参数之前上传选项的内容来解决这个问题,但是我仍然很好奇知道我是否可以类型测试或者转换一个对象泛型参数)到一个选项,而不用担心这个选项包含什么类型(假设当前的转换是有效的,即对象真的是一个选项)。

Update: I managed to get around this by upcasting the contents of the option before it becomes a parameter to this function, but I'm still curious to know if I can type-test or cast an object (or generic parameter) to an option without worrying about what type the option contains (assuming of course the cast is valid, i.e. the object really is an option).

推荐答案

目前没有任何好的方法来解决这个问题。

There isn't any nice way to solve this problem currently.

问题是你需要引入一个新的通用类型参数(当匹配选项<'a> 时),但是F#只允许在函数声明中定义通用类型参数。所以,你唯一的解决方案是使用一些反射技巧。例如,您可以定义隐藏此模式的活动模式:

The issue is that you'd need to introduce a new generic type parameter in the pattern matching (when matching against option<'a>), but F# only allows you to define generic type parameters in function declarations. So, your only solution is to use some Reflection tricks. For example, you can define an active pattern that hides this:

let (|SomeObj|_|) =
  let ty = typedefof<option<_>>
  fun (a:obj) ->
    let aty = a.GetType()
    let v = aty.GetProperty("Value")
    if aty.IsGenericType && aty.GetGenericTypeDefinition() = ty then
      if a = null then None
      else Some(v.GetValue(a, [| |]))
    else None

这将给你 code>包含 obj 任何选项类型:

This will give you None or Some containing obj for any option type:

let bind (x : obj) rest =   
    match x with    
    | SomeObj(x1) -> rest x1
    | _ -> failwith "Invalid type"

bind(Some 1) (fun n -> 10 * (n :?> int))

这篇关于如何从obj向下转换到选项&lt; obj&gt ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆