情景1
let map = Dictionary<string,obj>()
map.Add("1",10)
map.Add("2",10L)
map.Add("3","10")
这符合罚款
情景2
let map = Dictionary<string,(unit -> obj)>()
map.Add("1",fun() -> 10)
map.Add("2",fun() -> 10L)
map.Add("3",fun() -> "10")
这里编译器说它除了obj但在遇到10
情景3
let map = Dictionary<string,(unit -> 'a)>()
map.Add("1",fun() -> 10)
map.Add("2",fun() -> 10L)
map.Add("3",fun() -> "10")
这里编译器接受第一个条目,但它会导致'a被约束为int,导致接下来的两个条目失败,因为它们不是int
第一个问题:为什么它在场景1中编译时没有在场景2中编译?
第二个问题:无论如何都要阻止'a在场景3中受到限制,或者是否存在某种可以使用的模式,这种模式可以在F#中的集合中实现不同类型(特别是在本例中的函数类型)?
值(obj /'a)的唯一用途是println "%A"
的参数,我不明白它为什么不能。
答案 0 :(得分:2)
在方案1中,编译器自动将map.Add
的参数从int
等转发到obj
,因为它可以看到map.Add
期望obj
。
在方案2中,它无法执行此操作,因为unit -> int
到unit -> obj
没有可用的上传 - 您无法通过在函数周围手动插入upcast
来进行转换。
理论上,编译器可以改变函数的主体,但是在调用map.Add
时,自动插入强制转换纯粹是本地的。
您不能阻止'a
在方案3中受到约束,因为运行时要求特定对象具有特定类型 - 即使您只以特定方式使用这些值,编译器和运行时也不会做那种看待它所需的全局分析。