将字符串文字限制为仅限文本

时间:2012-07-19 01:31:33

标签: haskell ghc string-literals overloaded-strings

我知道OverloadedStrings语言编译指示在所有字符串文字周围包含一个隐式fromString。我想要做的事实上不是重载字符串,而只是改变它们的含义,以便它们总是变成Text,因此,使用字符串文字作为字符列表应该导致类型错误。

在没有为该类导入IsString实例的情况下导入String类似乎是不可能的。 ghc是否为我提供了一些限制字符串文字仅限Text的方法?

2 个答案:

答案 0 :(得分:43)

这有点过分,但一种解决方案是将OverloadedStringsRebindableSyntax结合起来。 RebindableSyntax扩展导致Haskell语法用于引用范围内的任何函数的所有隐式函数调用;例如,整数文字使用任何fromIntegral,不一定是Prelude.fromIntegral。作为副作用,不再隐式导入Prelude,因此您必须手动执行此操作。只要你导入它,就不应该隐式使用错误的函数语法问题(我想 - 我实际上并没有使用这种技术)。与OverloadedStrings结合使用时,这会导致"foo"转换为fromString "foo",范围内的fromString,不一定是Data.String.fromString "foo"。因此,将fromStringpack同义,就能做到你想要的。一个完整的例子:

{-# 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

另外,请注意:RebindableSyntax上的GHC手册部分未提及fromString功能,OverloadedStrings部分未提及RebindableSyntax }}。这个不应该工作没有理由,但我认为这意味着这个解决方案在技术上依赖于无证件的行为。

答案 1 :(得分:1)

现在不是一种实现这一目标的方法,但最终可能是GHC feature proposal under discussion中提出的instance force,你要说

instance force IsString Text

在你的模块中。这是该提案的主要推动范例之一。