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#:警告FS0020:此表达式的类型应为';单位';,但是有类型';布尔';_F#_Unit Type - Fatal编程技术网

F#:警告FS0020:此表达式的类型应为';单位';,但是有类型';布尔';

F#:警告FS0020:此表达式的类型应为';单位';,但是有类型';布尔';,f#,unit-type,F#,Unit Type,我试图通过研究一些欧拉问题来学习F#,但我发现了一个我一直无法解决的问题。这是我天真的解决办法 let compute = let mutable f = false let mutable nr = 0 while f = false do nr <- nr + 20 f = checkMod nr nr 让我们来计算= 设可变f=false 设可变nr=0 而f=假do nr下一行: f = checkMod nr 这

我试图通过研究一些欧拉问题来学习F#,但我发现了一个我一直无法解决的问题。这是我天真的解决办法

let compute =
    let mutable f = false
    let mutable nr = 0
    while f = false do
        nr <- nr + 20
        f = checkMod nr
    nr
让我们来计算=
设可变f=false
设可变nr=0
而f=假do
nr下一行:

f = checkMod nr
这是一个平等的检查,而不是一个任务,因为我相信你是有意的。将其更改为:

f <- checkMod nr
f在f#中,如果你来自命令式语言,就要稍微习惯一下。
while
表达式中的每一行必须计算为
unit
(从C++/C#开始考虑
void
)。然后,整个表达式的计算结果也是
unit

在示例中:

nr <- nr + 20
计算为如上所述的
bool
。这将导致报告警告消息。如果您愿意,实际上可以关闭警告。只需将以下内容放在文件的顶部:

#nowarn "0020"

如果您试图采用函数式风格,请尽量避免可变值

例如:

let nr =
   let rec compute nr =  
      if checkMod nr then nr else compute (nr + 20)
   compute 0     
let multi20 = Seq.initInfinite (fun i -> i*20)
let compute = multi20 |> Seq.find checkMod

由于我可以想象这个weg页面将成为查找有关警告FS0020信息的“标准”场所,下面是我对三种最常见的警告情况的快速总结,以及如何修复它们

故意丢弃仅因副作用而调用的函数的结果:

// you are calling a function for its side-effects, intend to ignore result    
let Example1Orig() =
    let sb = new System.Text.StringBuilder()
    sb.Append("hi")       // warning FS0020
    sb.Append(" there")   // warning FS0020
    sb.ToString()

let Example1Fixed() =
    let sb = new System.Text.StringBuilder()
    sb.Append("hi") |> ignore
    sb.Append(" there") |> ignore
    sb.ToString()
// the warning is telling you useful info 
// (e.g. function does not have an effect, rather returns a value)
let Example2Orig() =
    let l = [1;2;3] 
    List.map (fun x -> x * 2) l    // warning FS0020
    printfn "doubled list is %A" l

let Example2Fixed() =
    let l = [1;2;3] 
    let result = List.map (fun x -> x * 2) l
    printfn "doubled list is %A" result
// '=' versus '<-'
let Example3Orig() =
    let mutable x = 3
    x = x + 1          // warning FS0020
    printfn "%d" x    

let Example3Fixed() =
    let mutable x = 3
    x <- x + 1
    printfn "%d" x    
警告很有用,指出错误(函数无效):

// you are calling a function for its side-effects, intend to ignore result    
let Example1Orig() =
    let sb = new System.Text.StringBuilder()
    sb.Append("hi")       // warning FS0020
    sb.Append(" there")   // warning FS0020
    sb.ToString()

let Example1Fixed() =
    let sb = new System.Text.StringBuilder()
    sb.Append("hi") |> ignore
    sb.Append(" there") |> ignore
    sb.ToString()
// the warning is telling you useful info 
// (e.g. function does not have an effect, rather returns a value)
let Example2Orig() =
    let l = [1;2;3] 
    List.map (fun x -> x * 2) l    // warning FS0020
    printfn "doubled list is %A" l

let Example2Fixed() =
    let l = [1;2;3] 
    let result = List.map (fun x -> x * 2) l
    printfn "doubled list is %A" result
// '=' versus '<-'
let Example3Orig() =
    let mutable x = 3
    x = x + 1          // warning FS0020
    printfn "%d" x    

let Example3Fixed() =
    let mutable x = 3
    x <- x + 1
    printfn "%d" x    
混淆赋值运算符和相等比较运算符:

// you are calling a function for its side-effects, intend to ignore result    
let Example1Orig() =
    let sb = new System.Text.StringBuilder()
    sb.Append("hi")       // warning FS0020
    sb.Append(" there")   // warning FS0020
    sb.ToString()

let Example1Fixed() =
    let sb = new System.Text.StringBuilder()
    sb.Append("hi") |> ignore
    sb.Append(" there") |> ignore
    sb.ToString()
// the warning is telling you useful info 
// (e.g. function does not have an effect, rather returns a value)
let Example2Orig() =
    let l = [1;2;3] 
    List.map (fun x -> x * 2) l    // warning FS0020
    printfn "doubled list is %A" l

let Example2Fixed() =
    let l = [1;2;3] 
    let result = List.map (fun x -> x * 2) l
    printfn "doubled list is %A" result
// '=' versus '<-'
let Example3Orig() =
    let mutable x = 3
    x = x + 1          // warning FS0020
    printfn "%d" x    

let Example3Fixed() =
    let mutable x = 3
    x <- x + 1
    printfn "%d" x    

/'='与'我已经用命令式编程很长时间了,所以习惯函数式编程的思维方式需要一段时间

在您的示例中,您试图找到通过checkMod测试的20个中的第一个倍数。这就是为什么。对于功能如何部分,我建议浏览序列可用的方法。您需要的是通过测试的序列的第一个元素(20的倍数),如下所示:

let nr =
   let rec compute nr =  
      if checkMod nr then nr else compute (nr + 20)
   compute 0     
let multi20 = Seq.initInfinite (fun i -> i*20)
let compute = multi20 |> Seq.find checkMod
第一个let生成一个无限多的二十个元素的列表(我自己编的)。第二个let在所述列表中找到通过测试的第一个数字。您的任务是确保确实有一个数字将通过测试,但对于命令式代码来说,这当然也是正确的

如果你想把上面的两行压缩成一行,你也可以写

let computeCryptic = Seq.initInfinite ((*) 20) |> Seq.find checkMod

但我发现,在代码中使用这样的特技可能会在几周后试图阅读时导致头痛。

与Brian的帖子一样,这里有另一种获得警告FS0020的方法:简而言之,我无意中对函数参数进行了双重设置

作为一名F#新手,我在调试下面的代码时遇到了困难,第二行(让gdp…)给出了警告FS0020:这个表达式应该有'unit'类型,但有'string->^a->unit)*string*float'类型。事实证明,线路根本不是问题;相反,是printfn行出错了。从参数列表中删除逗号分隔符修复了此问题

for country in wb.Regions.``Arab World``.Countries do
  let gdp = country.Indicators.``GDP per capita (current US$)``.[2010]
  let gdpThous = gdp / 1.0e3
  printfn "%s, %s (%.2f)" country.Name, country.CapitalCity, gdpThous

谢谢,这就解决了问题,真不敢相信我在盯着它看了这么久之后错过了:)我的目标是学习函数式编程风格,但没有多少时间来学习,这是一个非常缓慢的过程。是的,很公平。函数式编程对以前只使用命令式语言(例如C/C#/Java)的程序员来说常常是一个巨大的冲击。它需要一种完全不同的思维方式,这种思维方式可以随着时间的推移而学习。但F#的一个好处是,你可以从熟悉的编码风格(基本的)开始在仍然高效的情况下,您可以编写命令式代码,这一事实使您可以优化代码的一小部分,而不必使用其他语言。@gradbot:没错-虽然只有当a)所有功能等价物(通常至少有几个)效率较低时才应该如此,在这种情况下,效率/绩效非常重要@詹姆斯·胡加德:这是一个公平的观点,尽管我倾向于建议直接进入功能性的东西,强迫自己以适当的方式思考是最有用的。至少为我工作过。:)获得此错误的另一种刺激方法是忘记破折号:x