Преобразование списка символов (или массива) в строку

как преобразовать из списка символов в строку?

Иными словами, как мне отменить List.ofSeq "abcd"?

UPDATE: new System.String (List.ofSeq "abcd" |> List.toArray) |> printfn "%A" работает нормально, с или без new, но List.ofSeq "abcd" |> List.toArray) |> new System.String |> printfn "%A" завершается с ошибкой. Почему?

Ответ 1

Я задал аналогичный вопрос ранее. Похоже, что конструкторы объектов не являются составными, поэтому вы не можете передавать их как функцию.

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"

Обновление Конструкторы являются первоклассными функциями с F # 4.0

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

Ответ 2

Работа со строками в F # иногда немного неудобна. Я бы, вероятно, использовал тот же код, что и Дарио. Грамматика F # не позволяет использовать конструкторы в качестве функций первого класса, поэтому вы, к сожалению, не можете обрабатывать всю обработку в одном конвейере. В общем, вы можете использовать статические члены и методы экземпляра в качестве функций первого класса, но не свойства экземпляра или конструкторы.

Во всяком случае, есть очень неприятный трюк, который вы можете использовать, чтобы превратить конструктор в значение функции. Я бы не рекомендовал его использовать, но я был очень удивлен, увидев, что он действительно работает, поэтому я подумал, что, возможно, стоит поделиться им:

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

Это определяет функцию, которая будет включена в момент компиляции, что требует, чтобы параметр первого типа имел конструктор, который принимает значение параметра второго типа. Это указано как ограничение времени компиляции (поскольку .NET-генераторы не могут это выразить). Кроме того, F # не позволяет вам указывать это, используя обычный синтаксис для указания ограничений конструктора (который должен принимать unit в качестве аргумента), но вы можете использовать скомпилированное имя конструкторов. Теперь вы можете написать, например:

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

И вы также можете использовать результат ctor как первоклассную функцию:

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

Как я уже сказал, я думаю, что это в основном любопытство, но довольно интересное:-).

Ответ 3

Ваш подход:

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

- это решение, которое я обычно тоже получаю.

Система грамматики/типа F # просто кажется неспособной распознать конструктор .NET, такой как new String, как функция curried (что мешает вам использовать конвейерную обработку).

Ответ 4

Просто столкнулся с подобной проблемой и придумал следующие решения:

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