Автоматическое преобразование между String и Data.Text в haskell
Как отметил Никита Волков в своем вопросе Data.Text vs String, я также задался вопросом, почему мне приходится иметь дело с различными реализациями строк type String = [Char]
и Data.Text
в Haskell. В моем коде я часто использую функции pack
и unpack
.
Мой вопрос: есть ли способ автоматического преобразования между обоими строковыми типами, чтобы я мог часто писать pack
и unpack
?
В других языках программирования, таких как Python или JavaScript, есть, например, автоматическое преобразование между целыми числами и поплавками, если это необходимо. Могу ли я достичь чего-то подобного в haskell? Я знаю, что указанные языки слабо типизированы, но я слышал, что С++ имеет аналогичную функцию.
Примечание. Я уже знаю расширение языка {-# LANGUAGE OverloadedStrings #-}
. Но, как я понимаю, эти языковые расширения применяются только к строкам, определенным как "..."
. Я хочу иметь автоматическое преобразование для строк, которые я получил от других функций, или у меня есть аргументы в определениях функций.
Расширенный вопрос: Haskell. Текст или Bytestring охватывает также разницу между Data.Text
и Data.ByteString
. Есть ли способ автоматического преобразования между тремя строками String
, Data.Text
и Data.ByteString
?
Ответы
Ответ 1
Нет.
Haskell не имеет скрытых принуждений по техническим, философским и почти религиозным причинам.
Как комментарий, преобразование между этими представлениями не является бесплатным, и большинству людей не нравится идея, что скрытые и потенциально дорогостоящие вычисления скрываются. Кроме того, при строках как ленивых списках принудительное их значение Text
может не заканчиваться.
Мы можем автоматически преобразовывать литералы в Text
с помощью OverloadedString
путем десурации строкового литерала "foo"
до fromString "foo"
и fromString
для Text
просто вызывает pack
.
Вопрос может состоять в том, чтобы спросить, почему вы так много принуждаете? Есть ли какие-то причины, по которым вам нужно unpack
Text
значения так часто? Если вы постоянно меняете их на строки, это немного побивает цель.
Ответ 2
Почти Да: Data.String.Conversions
Библиотеки Haskell используют разные типы, поэтому есть много ситуаций, в которых нет выбора, кроме как сильно использовать преобразование, отвратительное, поскольку оно - переписывание библиотек не считается реальным выбором.
Я вижу две конкретные проблемы, одна из которых потенциально является значительной проблемой для принятия Haskell:
-
кодирование заканчивается тем, что требует конкретных знаний об использовании библиотек, которые вы хотите использовать. Это большая проблема для языка высокого уровня.
-
производительность на простых задачах плоха - это большая проблема для обобщенного языка.
Реферат по конкретным типам
В моем опыте первой проблемой является время, потраченное на угадывание имени пакета, содержащего правильную функцию для сантехники между библиотеками, которые в основном работают с одними и теми же данными.
Для этой проблемы есть действительно удобное решение: Data.String.Conversions
package, если вам нравится UTF-8 как ваш по умолчанию.
Этот пакет предоставляет одну функцию преобразования cs
между несколькими различными типами.
-
String
-
Data.ByteString.ByteString
-
Data.ByteString.Lazy.ByteString
-
Data.Text.Text
-
Data.Text.Lazy.Text
Итак, вы просто import Data.String.Conversions
и используете cs
, который выведет правильную версию функции преобразования в соответствии с типами ввода и вывода.
Пример:
import Data.Aeson (decode)
import Data.Text (Text)
import Data.ByteString.Lazy (ByteString)
import Data.String.Conversions (cs)
decodeTextStoredJson' :: T.Text -> MyStructure
decodeTextStoredJson' x = decode (cs x) :: Maybe MyStructure
NB: В GHCi у вас обычно нет контекста, который дает целевой тип, поэтому вы направляете преобразование, явно указывая тип результата, например, для read
let z = cs x :: ByteString
Производительность и крик для "истинного" решения
Я пока не знаю ни одного истинного решения, но мы уже можем догадаться о направлении
- законно требовать преобразования, поскольку данные не изменяются;
- Наилучшая производительность достигается за счет не преобразования данных из одного типа в другой для административных целей;
- принуждение - зло - коэрцитивное, даже.
Таким образом, направление должно быть таким, чтобы эти типы не отличались друг от друга, т.е. согласовывали их под (или над) архивом, из которого они все бы вывели, позволяя составлять функции с использованием разных дериваций без необходимости конвертировать.
Nota: Я абсолютно не могу оценить возможности/потенциальные недостатки этой идеи. Могут быть некоторые очень звуковые пробки.