Использование перегруженных строк
OverloadedStrings
расширение действительно очень полезно, однако оно имеет некоторые недостатки.
Рассмотрим следующее определение функции:
someFunction :: ToJSSTring a => a -> IO ()
someFunction = js_function . toJSSTring
В этом случае, если я хочу передать литеральное значение, я должен явно добавить подпись типа, когда включен OverloadedStrings
:
someFunction ("This is plain string" :: String)
someFunction ("And this one is Text" :: Data.Text.Text)
Причина этой необходимости совершенно очевидна, я полагаю, что OverloadedStrings
был предназначен для облегчения передачи литеральных значений функциям, имеющим строгие сигнатуры типов, что позволяет разработчику писать pack
везде, где значение Text
необходимо.
Вопрос в том, есть ли способ, скажем, по умолчанию все строковые литералы без подписи типов к Text
или String
? Или я должен просто разделить мой код на общие функции (с ограничением типа ToJSString
) и произвольными, которые имеют строгие сигнатуры типов для своих аргументов?
Ответы
Ответ 1
Вы можете включить ExtendedDefaultRules
(https://www.fpcomplete.com/user/snoyberg/random-code-snippets/overloadedstrings-defaults):
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ExtendedDefaultRules #-}
import Data.Text (Text, pack)
newtype JSString = JSString Text
deriving Show
class ToJSString a where
toJSString :: a -> JSString
instance ToJSString [Char] where
toJSString = toJSString . pack
instance ToJSString Text where
toJSString = JSString
someFunction :: ToJSString a => a -> IO ()
someFunction = print . toJSString
main :: IO ()
main = someFunction "Hello World"
EDIT. Вы также можете добавить default (Text)
в начало своего модуля, чтобы по умолчанию использовать Text
вместо String
.