令人困惑的F#编译器消息

时间:2014-12-22 20:06:11

标签: f# unit-type

以下代码段说明了我遇到的错误。即使两个匹配分支返回相同的东西;我得到错误,“这个表达式应该有类型单位,但这里有类型'a - >单位”我不知道编译器想要什么......

open System.IO 

let FileContent contents =  
  match contents with  
  | "" -> None  
  | c -> Some(c)  

let WriteSomething (contents:string) =  
  let writer = new StreamWriter("")  
  writer.Write( contents ) |> ignore  

let DoStuffWithFileContents =  
  let reader = new StreamReader( "" )  
  let stuff = reader.ReadToEnd()  
  match stuff |> FileContent with  
  | Some(c) -> WriteSomething c  
               |> ignore  
  | None -> ignore  // <- error on "ignore"

2 个答案:

答案 0 :(得分:7)

ignore运算符实际上是一个函数,它接受单个输入并返回unit type(F#相当于void)。因此,当您-> ignore时,您将返回ignore功能。

而是使用()来表示unit类型的值:

  | Some(c) -> WriteSomething c  
               |> ignore  
  | None -> ()

但实际上,由于StreamWriter.Write返回void,所有这些ignore都是不必要的。您可以轻松地将其写为:

let WriteSomething (contents:string) =  
  let writer = new StreamWriter("")  
  writer.Write(contents)   

let DoStuffWithFileContents =  
  let reader = new StreamReader("")  
  let stuff = reader.ReadToEnd()  
  match stuff |> FileContent with  
  | Some(c) -> WriteSomething c  
  | None -> () 

甚至更好,请使用Option.iter

let WriteSomething (contents:string) =  
  let writer = new StreamWriter("")  
  writer.Write(contents)

let DoStuffWithFileContents =  
  let reader = new StreamReader("")  
  let stuff = reader.ReadToEnd()  
  stuff |> FileContent |> Option.iter(WriteSomething)

答案 1 :(得分:1)

通过在最后一行返回ignore,您将返回一个函数,而不是一个简单的值。

ignore的要点是将内容转换为()。您的最后一行可以直接返回()