Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么这会混淆F#编译器';s型推理?_F#_Closures_Type Inference - Fatal编程技术网

为什么这会混淆F#编译器';s型推理?

为什么这会混淆F#编译器';s型推理?,f#,closures,type-inference,F#,Closures,Type Inference,这里没问题: module Seq = let private rnd = Random Environment.TickCount let random = fun (items : 'T seq) -> let count = Seq.length items items |> Seq.nth (rnd.Next count) Seq.random的签名为项:Seq obj 有趣的是,如果我选择代

这里没问题:

module Seq =
    let private rnd = Random Environment.TickCount

    let random =
        fun (items : 'T seq) ->
            let count = Seq.length items
            items |> Seq.nth (rnd.Next count)
Seq.random
的签名为
项:Seq obj


有趣的是,如果我选择代码并点击
[Alt]+[Enter]
在F#Interactive中执行它,签名显示为
seq,这是由于所谓的。长话短说,语法值不能是泛型的,因为当发生突变时,它可能会破坏某些东西,而且编译器不能始终可靠地证明不变性。(注意,即使
random
在语义上是一个函数,但在语法上它仍然是一个值,这才是重要的)

但有时编译器可以证明是不变性的。这就是您的第一个示例起作用的原因:当
let
的右侧是一个直接向上的lambda表达式时,编译器可以确定它是不可变的,因此它允许该表达式通过

另一个例子是
让x=[]
——在这里,编译器可以看到nil列表
[]
是不可变的。另一方面,
let x=List.append[][]
将不起作用,因为编译器无法证明这种情况下的不变性

这种价值限制的“放松”是在F#中根据具体情况进行的。F#编译器只处理一些特殊情况:文本、lambda表达式等,但它没有一个完整的机制来证明一般的不变性。这就是为什么,一旦您跳出这些特殊情况,就不允许使用泛型值

从技术上讲,可以通过添加显式类型参数来解决这个问题。从逻辑上讲,这告诉编译器“是的,我知道这是一个泛型值,这就是我的意思”


非常有趣。我不知道泛型let绑定变成了无参数函数。这是否同样适用于
未选中的.defaultOf
和类似的核心库函数(看起来不一样)?是的<代码>序列空
是另一个例子。
module Seq =
    let random =
        let rnd = Random Environment.TickCount
        fun (items : 'T seq) ->
            let count = Seq.length items
            items |> Seq.nth (rnd.Next count)
let random<'t> : seq<'t> -> 't =
    let rnd = Random Environment.TickCount
    fun items ->
        let count = Seq.length items
        items |> Seq.nth (rnd.Next count)

let x = random [1;2;3]
let random() =
    let rnd = Random Environment.TickCount
    fun items ->
        let count = Seq.length items
        items |> Seq.nth (rnd.Next count)

let x = random() [1;2;3]