2010-02-28 3 views
12

Wie konvertiert man aus einer Liste von Zeichen in eine Zeichenfolge?Konvertieren Sie eine Liste von Zeichen (oder Array) in eine Zeichenfolge

Um es anders auszudrücken, wie kann ich List.ofSeq "abcd" umkehren?

UPDATE: new System.String (List.ofSeq "abcd" |> List.toArray) |> printfn "%A" scheint gut zu funktionieren, mit oder ohne new, aber List.ofSeq "abcd" |> List.toArray) |> new System.String |> printfn "%A" schlägt fehl. Warum?

Antwort

20

Ich fragte einmal eine similar question vorher. Es scheint, dass Objektkonstruktoren nicht zusammensetzbar sind, so dass Sie sie nicht als Funktion übergeben können.

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" 

aktualisieren Konstrukteurs sind erstklassige Funktionen wie von F # 4,0

List.ofSeq "abcd" |> List.toArray |> System.String |> printfn "%A" 
+0

OK, macht diese Einschränkung Sinn Performance-weise (eine Lambda schaffen, die sie wahrscheinlich schaden Leistung zu optimieren wahrscheinlich schwer kann die schwer zu erkennen). Irgendein Zeiger auf, warum 'neu' ist optional? Um das Erstellen von Objekten durch Reflektion besser mit der Ocaml/F # -Syntax zu verschmelzen? Vielen Dank! –

+0

Art von schwer zu einer der Antworten zu wählen, werde ich dieses wählen, weil es eine andere verwandte Frage verweist. :-) –

+0

"Es scheint, Objekt Konstruktoren sind nicht zusammensetzbar, so dass Sie sie nicht als Funktion übergeben können." Dies ändert sich endlich. https://github.com/fsharp/FSharpLangDesign/blob/master/FSharp-4.0/ClassNamesAsFunctionsDesignAndSpec.md – Endrju

4

Ihr Ansatz:

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

ist die Lösung, die ich in der Regel mit enden.

F # 's Grammatik/Typ-Inferenz-System scheint einfach nicht in der Lage, einen .NET-Konstruktor wie new String als Curry-Funktion zu erkennen (was verhindert, dass Sie Pipelining verwenden).

10

Arbeiten mit Zeichenketten in F # ist manchmal ein bisschen unangenehm. Ich würde wahrscheinlich den gleichen Code wie Dario verwenden. Die F # -Grammatik erlaubt es nicht, Konstruktoren als First-Class-Funktionen zu verwenden, so dass Sie leider nicht die gesamte Verarbeitung in einer einzigen Pipeline durchführen können. Im Allgemeinen können Sie statische Member und Instanzmethoden als First-Class-Funktionen verwenden, nicht jedoch Instanzeigenschaften oder Konstruktoren.

Wie auch immer, es gibt einen wirklich fiesen Trick, den Sie verwenden können, um einen Konstruktor in einen Funktionswert zu verwandeln. Ich würde nicht wirklich empfehlen es, aber ich war ziemlich überrascht zu sehen, dass es tatsächlich funktioniert, so dass ich dachte, es kann sich lohnen, sie teilen

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

Dies definiert eine Funktion, die bei der Kompilierung inlined werden, die erfordert, dass der erste Typparameter einen Konstruktor hat, der einen Wert des zweiten Typparameters annimmt. Dies wird als Kompilierzeit-Einschränkung angegeben (weil .NET-Generics dies nicht ausdrücken können). Außerdem können Sie in F # nicht die übliche Syntax zum Angeben von Konstruktoreinschränkungen angeben (die unit als Argument annehmen muss), aber Sie können den kompilierten Namen der Konstruktoren verwenden. Jetzt können Sie zum Beispiel schreiben:

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

Und Sie können auch das Ergebnis der ctor als First-Class-Funktion:

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

Wie gesagt, ich denke, das ist in erster Linie eine Kuriosität, sondern ein ziemlich interessant :-).

+0

+1: coolness !!! – Juliet

0

Gerade ähnliches Problem konfrontiert, und kam mit diesen Lösungen auf:

List.fold (fun str x -> str + x.ToString()) "" (List.ofSeq "abcd") 
Verwandte Themen