撰写全部和部分功能

时间:2013-10-01 10:00:30

标签: ocaml composition

请不要回答

这是Point-free: confused about where to put parenthesis的愚蠢副本我真的想删除这个问题。

谢谢!


我无法将头围绕在哪里,我应该将括号放在哪里才能使其正常工作:

let read_lines filename =
  let channel = open_in filename in
  Std.input_list channel;;

let print_lines filename =
  List.map print_string ((^) "\n") (read_lines filename);;

^这是我到目前为止的关闭。如果我的术语含糊不清:((^) "\n")就是我所说的部分函数(好吧,因为它不处理它的所有参数)。 print_string我称之为全函数,因为......好吧,它处理它的所有参数。

显然,我想要发生的是:

  1. List.map首先将((^) "\n")应用于列表元素。
  2. List.mapprint_string应用于#1的结果。
  3. 如何? :)

2 个答案:

答案 0 :(得分:1)

也许你想要那样的东西?

# let ($) f g = fun x -> f(g x);;
val ( $ ) : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>
# let f = print_string $ (fun s -> s^"\n");;
val f : string -> unit = <fun>
# List.iter f ["a";"b";"c";"d"];;
a
b
c
d
- : unit = ()
# let g = string_of_int $ ((+)1) $ int_of_string;;
val g : string -> string = <fun>
# g "1";;
- : string = "2"

你的代码没有用,因为缺少括号:

List.map print_string ((^) "\n") xs

被解析为

(List.map print_string ((^) "\n")) xs

当你预期

List.map (print_string ((^) "\n")) xs

答案 1 :(得分:1)

一些事情:List.map可能不是你想要的,因为它会产生一个列表(单位值),而不仅仅是迭代。 ((^) "\n")可能也不是你想要的,因为预先换行符,"\n"是第一个参数。 (这不是Haskell中的一个部分,而是一个简单的部分应用程序。)

这是一个合理的解决方案,接近你想要的(我认为):

let print_lines filename =
  List.iter (fun str -> print_string (str ^ "\n")) (read_lines filename)

但我宁愿写

let print_lines filename =
  List.iter (Printf.printf "%s\n") (read_lines filename)

哪个更清晰,效率更高。