【问题标题】:F#: Type inference not finding the correct overloadF#:类型推断未找到正确的重载
【发布时间】:2013-06-28 19:06:30
【问题描述】:

我已经编写了一个函数并开始对其进行重构,但是我遇到了一些问题,即“无法根据此程序点之前的类型信息确定方法 'Round' 的唯一重载”。错误,但我不明白为什么。

let CheckValuesLin (lowValue, highValue) multiplier (sigFigs:int) =
    let arithmean (lowValue, highValue) =
        (lowValue + highValue) / 2.0
    let createRangeValue numberModifier meanfunction= 
        let mean = meanfunction (lowValue, highValue)
        let rangeValue = mean + (numberModifier mean) * multiplier
        Math.Round(rangeValue, sigFigs)
    let createRangeValues valueCreatingFunction=
        (createRangeValue makeNegative arithmean, createRangeValue keepPositive arithmean)
    let greatestMinValue, lowestMaxValue = createRangeValues createRangeValue
    (greatestMinValue, lowestMaxValue)

失败的线是 Math.Round 线,当我将 range 设置为 range: float 时它消失了。这让我感到困惑,因为我悬停的所有内容似乎都已经推断出正确的类型,包括范围和平均值。

我不介意输入类型提示,我只是想知道它为什么会失败。

【问题讨论】:

    标签: f# type-inference


    【解决方案1】:

    问题在于 F# 类型推断严格是从左到右,从上到下。

    createRangeValue函数中,编译器只能推断出所有的值都是数字,没有强制类型为float

    虽然稍后对arithmean 的调用似乎会给出一些浮点类型的值,但这发生在对Round 的调用之后,因此编译器无法推断类型。

    编辑更多细节: 本质上,编译器会看到:

    let lowValue = 0.0 //I am being genrous by making this have a type
    let highValue = 0.0
    let sigFigs = 0 //this type is known
    let createRangeValue (numberModifier) (meanfunction) multiplier= 
        let mean = meanfunction (lowValue, highValue)    
        let rangeValue = mean + (numberModifier mean) * multiplier
        Math.Round(rangeValue, sigFigs)
    

    在这种情况下,rangeValue 可以是 floatDecimal,因为两者都将满足所有存在的约束。

    对我来说,这很好用

    open System
    let makeNegative a = -a
    let keepPositive a = a
    let CheckValuesLin (lowValue, highValue) multiplier (sigFigs:int) =
        let arithmean (lowValue, highValue) =
            (lowValue + highValue) / 2.0
        let createRangeValue numberModifier (meanfunction: float * float -> float)= 
            let mean = meanfunction (lowValue, highValue)
            let rangeValue = mean + (numberModifier mean) * multiplier
            Math.Round(rangeValue, sigFigs)
        let createRangeValues valueCreatingFunction=
            (createRangeValue makeNegative arithmean, createRangeValue keepPositive arithmean)
        let greatestMinValue, lowestMaxValue = createRangeValues createRangeValue
        (greatestMinValue, lowestMaxValue)
    

    【讨论】:

    • 如果是这种情况,float*float->float 类型的“meanFunction”上的类型提示不会解决问题吗?它没有,所以也许我误解了你的答案?
    • @Sean - numberModifier 中仍然有一个时间不足的类型 - 尽管我认为它应该被推断为 float -> float,但由于某种原因没有这样做。添加此类型注释可以解决问题,但我不确定为什么
    • @Sean - 我最初遇到了和你一样的错误,但是重置我的 fsi 让它消失了,我添加了只在 meanfunction 上对我有用的带有注释的代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2013-05-05
    相关资源
    最近更新 更多