Search code examples
haskelllanguage-extensionghcjsoverloaded-strings

Using Overloaded Strings


OverloadedStrings extension is really very useful, however it has some downsides. Consider the following function definition:

someFunction :: ToJSSTring a => a -> IO ()
someFunction = js_function . toJSSTring

In this case when if I want to pass a literal value I have to add a type signature explicitly when OverloadedStrings is enabled:

someFunction ("This is plain string" :: String)
someFunction ("And this one is Text" :: Data.Text.Text)

The reason for this necessity is quite obvious, I suppose OverloadedStrings was designed to ease the passing of literal values to functions that have strict type signatures, making the developer free from writing packs everywhere where a Text value is needed.

The question is there any way, say, to default all string literals without type signatures to Text, or String? Or should I just split my code to general functions (with the ToJSString type constraint) and arbitrary ones, which have strict type signatures for their arguments?


Solution

  • You can turn on ExtendedDefaultRules as well (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 You may also want to add default (Text) to the top of your module to have it use Text instead of String by default.