2010-02-28 19 views
12

Jak przekonwertować listę znaków na łańcuch?Konwertuj listę znaków (lub tablicę) na ciąg znaków

Innymi słowy, jak mogę cofnąć List.ofSeq "abcd"?

AKTUALIZACJA: new System.String (List.ofSeq "abcd" |> List.toArray) |> printfn "%A" wydaje się działać dobrze, z lub bez new, ale List.ofSeq "abcd" |> List.toArray) |> new System.String |> printfn "%A" kończy się niepowodzeniem. Czemu?

Odpowiedz

20

Raz zapytałem o numer similar question. Wydaje się, że konstruktory obiektów nie są kompozycyjne, więc nie można ich przekazać jako funkcji.

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" 

Aktualizacja Konstruktorzy są funkcje pierwszej klasy poczynając od F # 4,0

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

OK, ograniczenie to ma sens z punktu widzenia wydajności (tworzenie lambda, która jest prawdopodobnie trudno zoptymalizować dala prawdopodobnie mogą zranić wydajności w sposób, który jest trudny do wykryć). Każdy wskaźnik, dlaczego "nowy" jest opcjonalny? Czy tworzenie obiektów poprzez odbicie lepiej komponuje się ze składnią Ocaml/F #? Dzięki! –

+0

Trudno wybrać jedną z odpowiedzi, wybiorę tę, ponieważ odwołuje się do innego pokrewnego pytania. :-) –

+0

"Wygląda na to, że konstruktory obiektów nie są kompozycyjne, więc nie można ich przekazać jako funkcji." To się ostatecznie zmienia. https://github.com/fsharp/FSharpLangDesign/blob/master/FSharp-4.0/ClassNamesAsFunctionsDesignAndSpec.md – Endrju

4

Twoje podejście:

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

jest rozwiązaniem I zazwyczaj kończy się zbyt.

System wnioskowania gramatycznego typu F # po prostu nie jest w stanie rozpoznać konstruktora .NET, takiego jak new String, jako funkcji curry (co uniemożliwia korzystanie z potoku).

10

Praca z ciągami znaków w F # jest czasem nieco niewygodne. Prawdopodobnie użyłbym tego samego kodu co Dario. Gramatyka F # nie zezwala na używanie konstruktorów jako funkcji pierwszej klasy, więc niestety nie można wykonać całego przetwarzania w jednym potoku. Zasadniczo można używać elementów statycznych i metod instancji jako funkcji pierwszej klasy, ale nie właściwości instancji lub konstruktorów.

W każdym razie istnieje naprawdę nieprzyjemna sztuczka, której można użyć do przekształcenia konstruktora w wartość funkcji. Nie polecam właściwie go używać, ale byłem bardzo zaskoczony, aby zobaczyć, że to rzeczywiście działa, więc pomyślałem, że może warto dzielić go:

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

ten definiuje funkcję, która zostanie włączonych w czasie kompilacji, która wymaga, aby pierwszy parametr type miał konstruktor, który przyjmuje wartość parametru drugiego typu. Jest to określone jako ograniczenie podczas kompilacji (ponieważ generics .NET nie może tego wyrazić). Ponadto F # nie pozwala na określenie tego przy użyciu zwykłej składni do określania ograniczeń konstruktora (która musi przyjąć unit jako argument), ale można użyć skompilowanej nazwy konstruktorów. Teraz można napisać na przykład:

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

I można również użyć wyniku ctor jako pierwszej klasy funkcji:

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

Jak powiedziałem, myślę, że jest to przede wszystkim ciekawość, ale całkiem ciekawy :-).

+0

+1: chłód !!! – Juliet

0

Wystarczy obliczu podobny problem i wymyślił tego rozwiązania:

List.fold (fun str x -> str + x.ToString()) "" (List.ofSeq "abcd") 
Powiązane problemy