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

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"

РЕДАКТИРОВАТЬ Вы также можете добавить default (Text) в верхней части вашего модуля, чтобы использовать его Text вместо String по умолчанию.

Другие вопросы по тегам