我知道语言编译指示包含所有字符串文字OverloadedStrings
的隐含。fromString
我想做的实际上并不是重载字符串,而只是改变它们的含义,以便它们总是变成Text
,因此,使用字符串文字作为字符列表应该会导致类型错误。
在不导入该类的实例的情况下导入IsString
该类似乎是不可能的。String
ghc 是否为我提供了一些将字符串文字限制为Text
仅的方法?
我知道语言编译指示包含所有字符串文字OverloadedStrings
的隐含。fromString
我想做的实际上并不是重载字符串,而只是改变它们的含义,以便它们总是变成Text
,因此,使用字符串文字作为字符列表应该会导致类型错误。
在不导入该类的实例的情况下导入IsString
该类似乎是不可能的。String
ghc 是否为我提供了一些将字符串文字限制为Text
仅的方法?
这有点矫枉过正,但一种解决方案是将 and 结合OverloadedStrings
起来RebindableSyntax
。该RebindableSyntax
扩展导致 Haskell 语法使用的所有隐式函数调用引用范围内的任何函数;例如,整数文字使用 any 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
. 没有理由这不应该起作用,但我认为这意味着该解决方案在技术上依赖于未记录的行为。
现在不是实现这一点的方法,但也许最终,是在讨论instance force
中的GHC 功能提案中提出的,你会说
instance force IsString Text
在你的模块中。这是该提案的主要激励示例之一。