user797257
user797257

Reputation:

Compose total and partial functions

I can't wrap my head around where should I put parenthesis to get it working:

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);;

^ This is the closes I've got so far. If my terminology is vague: ((^) "\n") is what I call partial function (well, because it doesn't handle all of its arguments). print_string I call total function because... well, it handles all of its arguments.

Obviously, what I would like to happen is that:

  1. List.map applies first ((^) "\n") to the element of the list.
  2. List.map applies print_string to the result of #1.

How? :)

Upvotes: 0

Views: 312

Answers (2)

gsg
gsg

Reputation: 9377

A few things: List.map is probably not what you want, since it will produce a list (of unit values) rather than just iterating. ((^) "\n") is probably also not what you want, as it prepends a newline, the "\n" being the first argument. (This is not a section as in Haskell, but a straightforward partial application.)

Here's a reasonable solution that is close to what (I think) you want:

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

But I would rather write

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

Which is both clearer and more efficient.

Upvotes: 1

Kakadu
Kakadu

Reputation: 2839

Maybe you want something like that?

# 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"

Your code didn't work because missing parenthesis:

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

is parsed as

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

when you expected

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

Upvotes: 1

Related Questions