Generics 编译器重写F中的类型定义(泛型)#
情景1Generics 编译器重写F中的类型定义(泛型)#,generics,f#,type-inference,Generics,F#,Type Inference,情景1 let map = Dictionary<string,obj>() map.Add("1",10) map.Add("2",10L) map.Add("3","10") 在这里,编译器接受第一个条目,但它会将“a”约束为int,这会导致下两个条目失败,因为它们不是int 第一个问题:为什么它在场景1中编译,而在场景2中没有编译 第二个问题:在场景3中是否有防止“a”受到约束的方法,或者是否有某种模式可用于在F#中的集合中具有不同的类型(具体如本例中的函数类型) 值(obj
let map = Dictionary<string,obj>()
map.Add("1",10)
map.Add("2",10L)
map.Add("3","10")
在这里,编译器接受第一个条目,但它会将“a”约束为int,这会导致下两个条目失败,因为它们不是int
第一个问题:为什么它在场景1中编译,而在场景2中没有编译
第二个问题:在场景3中是否有防止“a”受到约束的方法,或者是否有某种模式可用于在F#中的集合中具有不同的类型(具体如本例中的函数类型)
值(obj/'a)的唯一用途是作为
println“%a”
的参数,我不明白为什么不能 在场景1中,编译器自动将参数向上转换为map。将从int
等添加到obj
,因为它可以看到map.Add
需要obj
在场景2中,它不能这样做,因为没有从unit->int
到unit->obj
的向上转换-您无法通过在函数周围手动插入upcast
来进行转换
理论上,编译器可以改为更改函数体,但在调用map.Add
时,强制转换的自动插入纯粹是局部的
在场景3中,您无法阻止'a
受到约束,因为运行时要求特定对象具有特定类型-即使您仅以特定方式使用这些值,编译器和运行时也不会进行必要的全局分析。对于场景2,您可以使用框
修复向上转换到obj
。例如,不要写10
而是写框10
。这也与以下最近的问题有关:谢谢你的快速回答!基于Jack P.答案,我认为处理这个问题的最佳方法是使用obj和box来处理每个条目?@Arkuray您不需要使用obj
和box
——只需box
。您可以使用一个通用函数来允许客户端代码提交任何单元->'a
,然后将其包装到一个新函数中,该函数执行以下装箱操作:让map=Dictionaryobj>()
和让addkey(f:unit->'a)=map.add(key,fun()->)框
let map = Dictionary<string,(unit -> obj)>()
map.Add("1",fun() -> 10)
map.Add("2",fun() -> 10L)
map.Add("3",fun() -> "10")
let map = Dictionary<string,(unit -> 'a)>()
map.Add("1",fun() -> 10)
map.Add("2",fun() -> 10L)
map.Add("3",fun() -> "10")