使用F#中的类型对象进行向下转换

时间:2014-08-25 12:35:24

标签: f#

let o1 = box SomeType()
let t = typeof<SomeType>

是否可以使用存储在其他对象(o1)中的Type信息向下转换(到SomeType)盒装对象(o1)?

最终目标是进行一种动态的函数调用。 我正在使用签名FSharpFunc&lt;'Pre,'Post&gt;存储函数在地图中:

// Lack of Covariance/Contravariance force me to define it as obj:
let functions = Map<string,obj>

let invoke f (pre : 'Pre when 'Pre : comparison) (post : 'Post when 'Post : comparison) =
    (unbox<FSharpFunc<'Pre,'Post>> f).Invoke(pre)

每当我在pre和post中传递正确的类型对象时,这种动态调用都会起作用。

知道了问题。我还在表单的地图中有调用的参数:

let data = Map<string,obj>
let conf = Map<string, Type>

其中conf将每个可能的字符串键的类型存储在数据中。

因此,给定一个功能键和一个正确的配置,我可以从数据中检索参数,以便为函数提供信息。但是要使这些工作起作用,我应该能够使用conf Types来转发数据值。

我怀疑这是不可能的,我知道我绕过静态类型安全(我很好)。在这种情况下,任何变通方法或替代方法?

1 个答案:

答案 0 :(得分:2)

我不确定我在此之后了解你的情况,所以这不是你问题的具体答案,而是一些可能对你有帮助的建议。

一般来说,听起来你想要某种存在类型。听起来像是

  • 您有各种类型的数据和

  • 您对该数据进行了操作

  • 您希望动态调用数据上的这些操作。

为了安全地制作这些内容,您应该将数据(或理想情况下的数据类型)和操作封装在一起而不是单独封装。当您知道数据的类型和对数据的可能操作时,将它们包装在一起,以便程序的其他部分不仅可以获取数据并尝试对数据执行不安全的操作。 (为了使这种封装通用且安全,允许类型安全地处理其类型不是静态知道的数据,你需要像first-class modules这样的东西。)

作为另一个建议,您可能更愿意使用box和unbox来装箱整个功能 领域和功能范围。请考虑以下wrapunwrap函数:

let wrap (a2b: 'a -> 'b) : obj -> obj =
  unbox<'a> >> a2b >> box<'b>

let unwrap (o2o: obj -> obj) : 'a -> 'b =
  box<'a> >> o2o >> unbox<'b>

function地图会有签名

val functions: Map<string, obj -> obj>

并存储包装的函数。要从地图调用函数,您可以使用所需类型打开先前包装的o2o函数:

(unwrap o2o : 'a when 'a: comparison -> 'b when 'b: comparison)

这样类型是安全的,但允许灵活的调用。