这有点矫枉过正,但一种解决方案是将OverloadedStrings 和RebindableSyntax 结合起来。 RebindableSyntax 扩展导致 Haskell 语法使用的所有隐式函数调用来引用范围内的任何函数;例如,整数文字使用任何fromIntegral,不一定是Prelude.fromIntegral。作为副作用,Prelude 不再隐式导入,因此您必须手动执行此操作。只要您做 导入它,隐式使用错误函数的语法不应该有任何问题(我认为——我实际上并没有使用过这种技术)。当与OverloadedStrings 结合使用时,这会导致"foo" 转换为fromString "foo",无论fromString 的范围是什么,不一定是Data.String.fromString "foo"。因此,将 fromString 与 pack 同义即可满足您的要求。一个完整的例子:
{-# LANGUAGE OverloadedStrings, RebindableSyntax #-}
import Prelude
import qualified Data.Text as T
import qualified Data.Text.IO as T
fromString :: String -> T.Text
fromString = T.pack
main :: IO ()
main = T.putStrLn "Hello, world!"
这工作正常,将 main 更改为 main = putStrLn "Hello, world!" 会产生所需的错误:
TestStrings.hs:11:17:
Couldn't match expected type `String' with actual type `T.Text'
Expected type: [Char] -> String
Actual type: String -> T.Text
In the first argument of `putStrLn', namely `"Hello, world!"'
In the expression: putStrLn "Hello, world!"
注释掉fromString 的定义会导致不同的错误:
TestStrings.hs:11:19:
Not in scope: `fromString'
Perhaps you meant `showString' (imported from Prelude)
如果您希望它同时处理严格文本和惰性文本,您可以定义自己的IsString 类型类,并将它们都设为实例;该类不必被称为IsString,只要它具有fromString 方法即可。
另外,提醒一句:GHC 手册中关于RebindableSyntax 的部分没有提到fromString 函数,而关于OverloadedStrings 的部分也没有提到RebindableSyntax。没有理由不应该工作,但我认为这意味着该解决方案在技术上依赖于未记录的行为。