Использование Перегруженных Строк


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 был разработан, чтобы облегчить передачу литеральных значений функциям, которые имеют строгие сигнатуры типа, что делает разработчика свободным от написания packs везде, где требуется значение Text.

Вопрос в том, можно ли, скажем, по умолчанию использовать все строковые литералы без сигнатур типа Text или String? Или я должен просто разделить свой код на общие функции (с ограничением типа ToJSString) и произвольные, которые имеют строгие сигнатуры типа для своих аргументов?

1 10

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 по умолчанию.