F# printfn anomaly

懵懂的女人 提交于 2019-12-13 15:15:11

问题


Can anyone please explain why this results in an error:

let xs = [| "Mary"; "Mungo"; "Midge" |]

Array.iter printfn xs

Whilst this does not:

Array.iter printfn [| "Mary"; "Mungo"; "Midge" |]

回答1:


The signature of printfn is Printf.TextWriterFormat<'a> -> 'a. The compiler infers literal values of strings as Printf.TextWriterFormat<unit> but cannot do so with dynamic strings.

You can help the compiler in the first example by adding correct type annotation:

let xs: Printf.TextWriterFormat<unit> [] = [| "Mary"; "Mungo"; "Midge" |]
Array.iter printfn xs

or using explicit constructors:

let xs = [| "Mary"; "Mungo"; "Midge" |]
Array.iter (fun s -> printfn <| Printf.TextWriterFormat<unit>(s)) xs

In general, it's too verbose to do so. Therefore, specifying format strings such as "%s" for strings and "%O" for types overriding ToString() method is the good way to go:

let xs = [| "Mary"; "Mungo"; "Midge" |]
Array.iter (printfn "%s") xs



回答2:


In addition to @pad's excellent answer.

The main reason for confusion is misunderstanding of what happens with the arguments. Let's look at single iteration. It supposed to be

printfn "%s" "Mary" // or whatever default format specifier instead of %s

but in fact, it is

printfn "Mary" ()

So "Mary" is not a string to be formatted. It is a format specifier, quite useless but well suitable for formatting a unit.

Try this modification to your sample:

Array.iter printfn [| "Mary %s"; "Mungo"; "Midge" |]

and it will refuse to compile.



来源:https://stackoverflow.com/questions/11708229/f-printfn-anomaly

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!