let list_to_string = (String.concat "") (List.map (String.make 1));;
This is wrong, but how do I make it understand that the argument is still to be supplied? The argument is expected to be of type char list
, I.e. the first function that needs to be applied to it is the (List.map (String.make 1))
, and then pass it to String.concat ""
. I think I've tried all combinations of parenthesis I could think of... no joy so far.
Help?
I also figured I could do it like this:
let ($) f g x = f (g x);;
let list_to_string = (String.concat "") $ (List.map (String.make 1));;
But just wanted to make sure there isn't a better way.
The real (and always perplexing) problem is that OCaml doesn't have a built-in function composition operator. So it's not so good out of the box for pointfree coding. If you really want to get fancy with it, you also need flip
, which inverts the order of the arguments of a two-argument function.
let flip f a b = f b a
At any rate, I don't see any problem with your solution once you've defined function composition as $
. You can leave out some of the parentheses:
# let lts = String.concat "" $ List.map (String.make 1);;
val lts : char list -> string = <fun>
As to efficiency, I assume this is more of a puzzle than a practical bit of code. Otherwise you should use the functions that Edwin suggests.
I don't think that partial application helps here, just write out the function parameter:
let list_to_string x = String.concat "" (List.map (String.make 1) x)
This isn't very efficient though, it would be better to create just one string and fill it with characters.
If you use Batteries then see Batstring.of_list, and if you use Core then see String.of_char_list
You can definitely just define a function composition operator in OCaml. It just can't be dot because that's already an operator in OCaml.
(* I just made up this symbol *)
let (^.^) f g x = f (g x)
let list_to_string = String.concat "" ^.^ List.map (String.make 1);;