.net - 为什么 F# 的 printfn 可以处理文字字符串,但不能处理字符串类型的值?

标签 .net f#

在以下 F# 代码中;我希望 printfn被调用了 3 次;每个都有一个字符串。但是,底线无法编译( The type 'string' is not compatible with the type 'Printf.TextWriterFormat<'a>' )。

前两行意味着这可以工作吗?它们不也只是字符串吗?

open System

printfn ("\r\n") // Works
printfn ("DANNY") // Works
printfn (DateTime.Now.ToLongTimeString()) // Doesn't compile

最佳答案

根据可能的解决方法,@Lee 的答案是正确的,但它没有描述您的代码会发生什么。
在表达式 printf "foo" , "foo"不是要格式化的字符串。相反,它是 输入格式化程序本身 .更具体地说,它是一个字符串文字,用于推断 TextWriterFormat<'T> 的实际类型。 .printf的签名是:

printf : TextWriterFormat<'T> -> 'T
由于printfn ("DANNY")不包含任何格式说明符,F# 编译器会推断出 TextWriterFormat<unit> , 整个表达式变为 printfn ("DANNY") () .
使用变量,不可能静态地预测将出现什么格式说明符。考虑 ToLongTimeString()方法能够返回 "%s" 的字符串或 "%d %d %d" ,返回函数的原型(prototype)是什么?
推断正确类型时,字符串文字可以正常工作,但变量或 let -绑定(bind)不起作用:
let foo1 = "foo"
let bar = printf foo // does not compile
[<Literal>] let foo2 = "foo";; // see update below
let bar = printf foo2 // compiles fine
无论如何,总是使用格式说明符看起来更安全:
printf "%s" "DANNY"
printf "%s" (DateTime.Now.ToLongTimeString())
更新 : 不要忘记输入双冒号 ;;[<Literal>] 之后值以避免在 VS2013 中出现警告 FS0058。

关于.net - 为什么 F# 的 printfn 可以处理文字字符串,但不能处理字符串类型的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18551851/

相关文章:

f# - 将 .NET 4.5 异步适配到 F#

constructor - F# 使用构造函数作为函数

.net - WPF 中的窗口所有者没有始终位于顶部的行为

C++ 简单字符检查

c# - 为什么 TcpClient 这么慢而且 CPU 很饿?

scala - F# 和 Scala 中的 ADT

f# - 在 Suave 中使用非拉丁字符

c# - 远程监控设计

c# - 如何让 WinForms 应用程序进入全屏模式

types - f#:在(归纳)类型中编码偶数和奇数?