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

Dan*_*ton 36 haskell ghc string-literals overloaded-strings

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

如果不导入IsString该类的String实例,则导入该类似乎是不可能的.ghc是否为我提供了一些限制字符串文字的方法Text

Ant*_*sky 44

这有点过分,但一个解决方案是结合OverloadedStringsRebindableSyntax.该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!"
Run Code Online (Sandbox Code Playgroud)

这工作正常,并更改mainmain = 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!"
Run Code Online (Sandbox Code Playgroud)

注释掉定义fromString会导致不同的错误:

TestStrings.hs:11:19:
    Not in scope: `fromString'
    Perhaps you meant `showString' (imported from Prelude)
Run Code Online (Sandbox Code Playgroud)

如果您希望它使用严格和惰性文本,您可以定义自己的IsString类型类,并使它们都成为实例; IsString只要它有一个fromString方法,就不必调用该类.

还有一句警告:GHC手册中的部分RebindableSyntax未提及该fromString功能,而该部分OverloadedStrings未提及RebindableSyntax.没有理由这不应该工作,但我认为这意味着该解决方案在技术上依靠无证行为.

  • @CetinSert:核心(带-O或-O2)是`main2 = Data.Text.unpackCString#"Hello,world!"`,所以至少它似乎不是在运行时通过`String`. (8认同)
  • 有意思,我没有想到这一点.它*有点矫枉过正,但我​​这样做的原因是同样的矫枉过正,所以这一切都很好. (4认同)
  • `T.pack`ing 是在编译时还是运行时发生? (2认同)