我已经编写了一个函数并且我已经开始重构它,但是我遇到了一些问题,“方法'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
时,它会消失。这让我感到困惑,因为我悬停的一切似乎已经推断出正确的类型,包括范围和均值。
我不介意把类型暗示,我只想知道它失败的原因。
答案 0 :(得分:2)
问题是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
可以是float
或Decimal
,因为两者都可以满足所有约束条件。
对我来说,这很好用
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)