限制字符串文字为纯文本(Restricting string literals to Text on

2019-07-30 12:21发布

我知道, OverloadedStrings语言编译包隐式fromString所有字符串文字周围。 我今天准备这样做实际上不是超载的字符串,而只是改变他们的意义,使他们总是变成Text ,因此,使用字符串文字作为字符列表应该导致一个类型错误。

这似乎是不可能的导入IsString课,而不会也导入String实例为类。 是否GHC提供了一些办法,我限制字符串文字到Text只?

Answer 1:

这是矫枉过正的一点点,而是一种解决方案是结合OverloadedStringsRebindableSyntax 。 该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!"

这工作得很好,并改变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!"

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

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

如果你想让它既严格又懒惰的文字工作,你可以定义自己的IsString类型的类,并且让他们两个实例; 类没有被称为IsString ,只是只要它有一个fromString方法。

另外,提醒一句:在GHC手册上的部分RebindableSyntax没有提及fromString功能,以及部分上OverloadedStrings没有提到RebindableSyntax 。 没有理由这不应该工作,但我认为这意味着该解决方案在技术上依靠无证行为。



Answer 2:

现在还没有办法做到这一点,但也许最终是instance force作为拟议中的讨论GHC功能建议 ,在那里你会说

instance force IsString Text

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



文章来源: Restricting string literals to Text only