Printfn值不是函数,不能在F#的交互窗口中应用

时间:2011-11-11 09:02:35

标签: f# fsi unit-type

这可能很简单,但我有一个带有简单示例函数的.fs文件。

let printHello = printfn "%A" "Hello"

我已使用

将搜索路径设置为.fs文件
>#I "PathToMyFSFile"

我已经使用

加载了我的文件
>#load "Test.fs"

哪个工作正常。现在我想调用实际打印hello到屏幕的功能,但那确实太难了

> Test.printHello;;
val it : unit = ()

尝试过Test.printHello();;同样但不起作用。我如何让它在屏幕上打印“Hello”?

3 个答案:

答案 0 :(得分:6)

您当前的printHello实际上并不是一个功能。要使它成为你需要做的功能

let printHello() = printfn "%A" "Hello"

noice ()。一切都应该有效。

编辑:

当编译器看到你的定义时

let printHello = printfn "%A" "Hello"

它将其作为简单的数据术语传递。例如,请考虑以下程序:

let printHello = printfn "%A" "Hello"
printfn "World"
printHello

这将打印"Hello"然后"World"printHello只有单位类型,所以什么都不做。将它与

进行比较
let printHello() = printfn "%A" "Hello"
printfn "World"
printHello()

这里printHello是一个函数。在这种情况下,该函数仅在显式调用时执行,因此打印"World"然后"Hello"

答案 1 :(得分:5)

正如John已经说过的那样,printHello不是函数 - 它是unit类型的值。当您给printfn所有必需的参数(就像您所做的那样)时,它会执行命令操作并返回unit(这是一种只有一个值写为()的类型)。您可以看到编写该声明立即进行打印:

> let printHello = printfn "%A" "Hello";;
"Hello"
val printHello : unit = ()

稍后使用printHello时,它只会引用此unit值(不包含任何信息)。

如果你想使它成为一个函数(类型为unit -> unit),每次执行它时都会执行某些操作,那么你可以使用John发布的样本。

函数printfn不是部分应用,因为您为它提供了所需的所有参数(因此它可以立即打印)。如果您想使用部分应用程序,可以使用以下内容:

> let printHello = printfn "%s %s" "Hello";; // Note - didn't give value for second %s
val printHello : string -> unit

现在printHello是一个等待第二个参数然后运行的函数:

> printHello "World";;
Hello World
val it : unit = ()

> printHello "F#";;
Hello F#
val it : unit = ()

答案 2 :(得分:1)

正如在其他答案中已经说过的那样,“printHello”设置为()是单位,printfn的返回值是(),控制台打印是副作用。

使用Lazy:

let printHello = Lazy (fun () ->printfn "%A" "Hello")

<强>样本

> Test.printHello.Value;;
"Hello"
val it : unit = ()
> Test.printHello.Value;;
val it : unit = () //only once

使用Seq:

let printHello = seq { printfn "%A" "Hello"; yield ()}

<强>样本

> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null]
> Test.printHello;;
"Hello"
val it : seq<unit> = seq [null] //many times