2014-11-06 49 views
10

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被设计成可以简化将字面值传递给具有严格类型签名的函数,从而使开发人员无需在需要Text值的地方编写pack

问题是否有任何方式,比如默认所有没有输入签名的字符串到TextString?或者我应该将我的代码分割为一般函数(类型约束为ToJSString)和任意函数,它们的参数都有严格的类型签名?

回答

22

您可以打开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

+1

你永远不会惊叹我!非常感谢。 – 2014-11-06 14:08:05