views:

354

answers:

3

In F# I want to transform a list of chars into a string. Consider the following code:

let lChars = ['a';'b';'c']

If I simply do lChars.ToString, I get "['a';'b';'c']". I'm trying to get "abc". I realize I could probably do a List.reduce to get the effect I'm looking for but it seems like there should be some primitive built into the library to do this.

To give a little context to this, I'm doing some manipulation on individual characters in a string and when I'm done, I want to display the resulting string.

I've tried googling this and no joy that way. Do I need to just bite the bullet and build a List.reduce expression to do this transformation or is there some more elegant way to do this?

+3  A: 

Have you tried

System.String.Concat(Array.ofList(lChars))
JaredPar
new System.String(lchars |> Array.of_list) works just as well too.
Juliet
@JaredPar, thanks! Just what the doctor ordered. I figured there must be some simple way to get at the string I wanted.@Juliet, you should have posted that as an answer :-) I would have voted it up because it's also an excellent suggestion.
Onorio Catenacci
+2  A: 
['a';'b';'c'] |> List.fold_left (fun acc c -> acc ^ (string c)) ""

Edited: Here is yet another funny way to do your task:

type t =
  | N
  | S of string
  static member Zero
    with get() = N
  static member (+) (a: t, b: t) = 
    match a,b with
      | S a, S b -> S (a+b)
      | N, _ -> b
      | _, N -> a

let string_of_t = function
  |N -> ""
  |S s -> s

let t_of_char c = S (string c)

['a'; 'b'; 'c'] |> List.map t_of_char |> List.sum |> string_of_t

Sadly, just extending System.String with 'Zero' member does not allow to use List.sum with strings.

Edited (answer to Juilet): Yes, you are right, left fold is slow. But i know more slow right fold :) :

#r "FSharp.PowerPack"

List.fold_right (String.make 1 >> (^)) ['a';'b';'c'] ""

and of course there is fast and simple:

new System.String(List.to_array ['1';'2';'3'])
ssp
One thing @ssp, I did try concatenating a string with the ^ operator and the compiler gave me a warning about OCaml compatibility. That is, it warned me that I should use + to concatenate strings.
Onorio Catenacci
fold_left is fun, but you need to remember that appending strings is O(n), and appending strings one char at a time is O(n^2)!
Juliet
+1  A: 

How many ways can you build a string in F#? Here's another handful:

let chars = ['H';'e';'l';'l';'o';',';' ';'w';'o';'r';'l';'d';'!']

//Using an array builder
let hw1 = new string [|for c in chars -> c|]

//StringBuilder-Lisp-like approach
open System.Text
let hw2 = 
    string (List.fold (fun (sb:StringBuilder) (c:char) -> sb.Append(c)) 
                      (new StringBuilder())
                       chars)

//Continuation passing style
let hw3 =
    let rec aux L k =
        match L with
        | [] -> k ""
        | h::t -> aux t (fun rest -> k (string h + rest) )
    aux chars id

Edit: timings may be interesting? I turned hw1..3 into functions and fed them a list of 500000 random characters:

  • hw1: 51ms
  • hw2: 16ms
  • hw3: er... long enough to grow a beard? I think it just ate all of my memory.
cfern