输入模块Printf

Sof*_*mur 4 ocaml types

Module Printf的文档中,我不了解其机制('a, out_channel, unit) format,以为我在实践中经常使用它.

例如,以下函数在编译时输入良好:

type t =
  { x: int;
    y: int }

let print (chan: out_channel) (co: t) : unit =
  Printf.fprintf chan "(%d, %d)" x y

let try (co0: t) (co1: t) =
  Printf.fprintf Pervasives.stdout "From %a To %a" print co0 print co1
Run Code Online (Sandbox Code Playgroud)

签名Printf.fprintf: out_channel -> ('a, out_channel, unit) format -> 'a,但我看不到('a, out_channel, unit) format匹配的内容"From %a To %a" print co0 print co1.

另外,签名printout_channel -> t -> unit,为什么print co0 print co1在代码中可以接受?

总之,任何人都可以解释一下Printf.fprintf Pervasives.stdout "From %a To %a" print co0 print co1打字的方式吗?

cam*_*ter 6

OCaml在格式字符串周围有一个打字黑客.这很简单,但对于简单且类型安全的printf功能非常有用.

通常,字符串文字键入为字符串:

# "(%d, %d)";;
- : string = "(%d, %d)"
Run Code Online (Sandbox Code Playgroud)

但如果它们具有"格式化"类型上下文,则它们不是:

# ( "(%d, %d)" : (_,_,_) format );;
- : (int -> int -> 'a, 'b, 'a) format = <abstr>
Run Code Online (Sandbox Code Playgroud)

OCaml类型检查器将文字作为格式字符串查看,然后对它使用特殊的类型规则:它在%d那里找到两个,并给出一个类型(int -> int -> 'a, 'b, 'a) format,这意味着它是一个格式字符串,可以采用2个整数并执行某些操作.

将字符串文字与Printf函数一起使用会给出相同的"格式"输入上下文,因此"(%d,%d)"的输入不仅仅是字符串,而是这种格式类型:

# Printf.fprintf stdout "(%d, %d)";;
- : int -> int -> unit = <fun>
Run Code Online (Sandbox Code Playgroud)

(t1, t2, t3) format 大致具有以下含义:

  • t1用于格式字符串作为函数的行为:"%d"对于此t1部分中的某些类型t应该具有"int - > t",因为它采用整数并执行某些操作(主要是打印).
  • t2是频道的类型
  • 当给出所有格式参数时,t3是最终结果类型.

您可以按如下方式验证它:

# (fun x -> Printf.fprintf stdout x, x) "(%d, %d)";;
- : (int -> int -> unit) * (int -> int -> unit, out_channel, unit) format =
(<fun>, <abstr>)
Run Code Online (Sandbox Code Playgroud)

"(%d, %d)"这里使用2个整数参数,它用于将字符串发送到类型为的stdout out_channel,然后最终返回unit.

实际上,formattype只是一个format6带有6个类型参数的别名,这3个类型参数用于其他格式字符串输入黑客.但我们不会从这里走得更远.

所以现在为"%a".

# ( "%a" : (_, out_channel, unit) format);;
- : ((out_channel -> 'a -> unit) -> 'a -> unit, out_channel, unit) format = <abstr>
Run Code Online (Sandbox Code Playgroud)

这告诉你Printf.fprintf stdout "%a"需要两个参数.一个是类型的函数,out_channel -> 'a -> unit另一个是'a.

如果你看到这种类型,那么很容易看出Printf.fprintf stdout "%a" print co0是好的类型.请注意,它不是Printf.fprintf stdout "%a" (print co0)(这是我"%a"多年前第一次看到的时候错误地阅读的内容.)

Printf.fprintf stdout "%a" print co0尝试co0使用打印机进行打印print.该子打印的通道当然stdout是给予的Printf.fprintf.