2014-11-06 63 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