什么是F#显式类型参数的用例?

时间:2013-04-05 02:43:31

标签: f# type-parameter

据我所知,值定义中的显式类型参数是克服“价值限制”问题的一种方法 还有其他需要使用它们的情况吗?

更新:我的意思是“显式通用构造”,其中type参数括在尖括号中,即

let f<'T> x = x

3 个答案:

答案 0 :(得分:5)

多态递归是另一种情况。也就是说,如果要在函数体中使用不同的泛型实例,则需要在定义上使用显式参数:

// perfectly balanced tree
type 'a PerfectTree = 
| Single of 'a
| Node of ('a*'a) PerfectTree

// need type parameters here
let rec fold<'a,'b> (f:'a -> 'b) (g:'b->'b->'b) : 'a PerfectTree -> 'b = function
| Single a -> f a
| Node t -> t |> fold (fun (a,b) -> g (f a) (f b)) g

let sum = fold id (+)

let ten = sum (Node(Node(Single((1,2),(3,4)))))

答案 1 :(得分:3)

这可能很少见,但是当你想要阻止进一步推广时(§14.6.7):

  

值和成员定义的显式类型参数定义可以影响类型推断和泛化的过程。特别是,包含显式通用参数的声明不会超出那些通用参数。例如,考虑这个函数:

let f<'T> (x : 'T) y = x
  

在类型推断期间,这将产生以下类型的函数,其中'_b是尚未解析的类型推理变量。

f<'T> : 'T -> '_b -> '_b
  

要允许对这些定义进行泛化,请删除显式通用参数(如果可以推断它们),或使用所需数量的参数,如以下示例所示:

let throw<'T,'U> (x:'T) (y:'U) = x

当然,您也可以使用类型注释来完成此操作。

答案 2 :(得分:1)

最明显的例子:编写一个函数来计算字符串的长度。

你必须写:

let f (a:string) = a.Length

你需要注释。如果没有注释,编译器就无法确定a的类型。存在其他类似的例子 - 特别是当使用设计用于C#的库时。

处理更新的答案:

同样的问题适用 - string变为A<string>,其方法get会返回string

let f (a:A<string>) = a.get().Length