4

方案 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 但在遇到时找到了 int10

方案 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",我看不出它为什么不能。

4

1 回答 1

2

在场景 1 中,编译器自动将map.Addfromint等的参数向上转换为obj,因为它可以看到map.Add期望obj

unit -> int在场景 2 中,它不能这样做,因为从to没有可用的向上unit -> obj转换 - 您无法通过手动插入upcast函数来进行转换。

理论上,编译器可以改为更改函数的主体,但强制类型转换的自动插入纯粹是在调用的地方map.Add进行的。

您无法避免'a在场景 3 中受到约束,因为运行时要求特定对象具有特定类型 - 即使您仅以特定方式使用值,编译器和运行时也不会进行全局分析需要看到这一点。

于 2013-06-04T15:27:54.803 回答