Преобразование списка символов (или массива) в строку
как преобразовать из списка символов в строку?
Иными словами, как мне отменить 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")