10

我正在学习 F#,但我不了解灵活类型的目的,或者更好的是,我无法理解编写此代码之间的区别:

set TextOfControl (c : Control) s = c.Text <- s

并写下:

set TextOfControl (c : 'T when 'T :> Control) s = c.Text <- s

Control班级在哪里System.Windows.Forms.Control

4

2 回答 2

19

你的例子没有区别。如果返回类型受到限制,您将开始看到差异:

let setText (c: Control) s = c.Text <- s; c
let setTextGeneric (c: #Control) s = c.Text <- s; c

let c = setText (TreeView()) "" // return a Control object
let tv = setTextGeneric (TreeView()) "" // return a TreeView object

请注意,这#Control是 的快捷方式'T when 'T :> Control类型约束对于为子类型创建泛型函数很重要。

例如,

let create (f: _ -> Control) = f()

let c = create (fun () -> Control()) // works
let tv = create (fun () -> TreeView()) // fails

对比

let create (f: _ -> #Control) = f()

let c = create (fun () -> Control()) // works
let tv = create (fun () -> TreeView()) // works
于 2013-01-22T12:23:57.163 回答
8

将值作为参数直接传递给 F# 函数时,编译器会自动向上转换该值(因此,如果函数采用Control,则可以为其TextBox赋值)。因此,如果使用灵活类型作为参数类型,则没有太大区别。

但是,如果函数采用例如 list ,则会有所不同'T list

// Takes a list of any subtype of object (using flexible type)
let test1<'T when 'T :> obj> (items:'T list) =
  items |> List.iter (printfn "%A")

// Takse a list, which has to be _exactly_ a list of objects
let test2 (items:obj list) =
  items |> List.iter (printfn "%A")

// Create a list of System.Random values (System.Random list)
let l = [new System.Random()]
test1 l // This works because System.Random is subtype of obj
test2 l // This does not work, because the argument has wrong type!
于 2013-01-22T12:07:58.947 回答