Convert a list of characters (or array) to a string

前端 未结 4 734
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-02-07 03:57

how does one convert from a list of characters to a string?

To put it another way, how do I reverse List.ofSeq \"abcd\"?

UPDATE: new System.St

相关标签:
4条回答
  • 2021-02-07 04:13

    I asked a similar question once before. It seems object constructors aren't composable so you can't pass them as a function.

    List.ofSeq "abcd" |> List.toArray |> (fun s -> System.String s) |> printfn "%A"
    List.ofSeq "abcd" |> List.toArray |> (fun s -> new System.String(s)) |> printfn "%A"
    

    Update Constructors are first-class functions as of F# 4.0

    List.ofSeq "abcd" |> List.toArray |> System.String |> printfn "%A"
    
    0 讨论(0)
  • 2021-02-07 04:17

    Just faced similar problem, and came up with this solutions:

    List.fold (fun str x -> str + x.ToString()) "" (List.ofSeq "abcd") 
    
    0 讨论(0)
  • 2021-02-07 04:19

    Working with strings in F# is sometimes a bit uncomfortable. I would probably use the same code as Dario. The F# grammar doesn't allow using constructors as first class functions, so you unfortunately cannot do the whole processing in a single pipeline. In general, you can use static members and instance methods as first class functions, but not instance properties or constructors.

    Anyway, there is a really nasty trick you can use to turn a constructor into a function value. I would not recommend actually using it, but I was quite surprised to see that it actually works, so I thought it may be worth sharing it:

    let inline ctor< ^R, ^T 
      when ^R : (static member ``.ctor`` : ^T -> ^R)> (arg:^T) =
       (^R : (static member ``.ctor`` : ^T -> ^R) arg)
    

    This defines a function that will be inlined at compile time, which requires that the first type parameter has a constructor that takes a value of the second type parameter. This is specified as a compile-time constraint (because .NET generics cannot express this). Also, F# doesn't allow you to specify this using the usual syntax for specifying constructor constraints (which must take unit as the argument), but you can use the compiled name of constructors. Now you can write for example:

    // just like 'new System.Random(10)'
    let rnd = ctor<System.Random, _> 10
    rnd.Next(10)
    

    And you can also use the result of ctor as first-class function:

    let chars = [ 'a'; 'b'; 'c' ]
    let str = chars |> Array.ofSeq |> ctor<System.String, _>
    

    As I said, I think this is mainly a curiosity, but a pretty interesting one :-).

    0 讨论(0)
  • 2021-02-07 04:24

    Your approach:

    new System.String (listOfChars |> List.toArray)
    

    is the solution I usually end up with too.

    F#'s grammar/type inference system simply seems unable to recognize a .NET constructor like new String as a curried function (which prevents you from using pipelining).

    0 讨论(0)
提交回复
热议问题