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

Posted

技术标签:

【中文标题】将字符串文字限制为仅文本【英文标题】:Restricting string literals to Text only 【发布时间】:2012-07-18 03:51:44 【问题描述】:

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

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

【问题讨论】:

要明确:手动将所有字符串文字包装在函数 asText :: Text -> Text; asText = id 中是不可接受的解决方案。 请注意,除非您有异常庞大的文字,否则 Text 可能不会比 String 更有效。当您从 IO 获取字符串时,文本真的会发光。 看这个haskell-cafe thread 【参考方案1】:

现在不是实现此目标的方法,但也许最终,是 GHC feature proposal under discussion 中提出的 instance force,您会说

instance force IsString Text

在您的模块中。这是该提案的主要激励示例之一。

【讨论】:

【参考方案2】:

这有点矫枉过正,但一种解决方案是将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 方法即可。

另外,提醒一句:GHC 手册中关于RebindableSyntax 的部分没有提到fromString 函数,而关于OverloadedStrings 的部分也没有提到RebindableSyntax。没有理由不应该工作,但我认为这意味着该解决方案在技术上依赖于未记录的行为。

【讨论】:

有趣,我没想到。这有点矫枉过正,但我​​这样做的原因是矫枉过正的味道,所以一切都很好。 T.packing 发生在编译时还是运行时? @CetinSert:核心(带有-O或-O2)是main2 = Data.Text.unpackCString# "Hello, world!",所以至少它在运行时似乎没有通过String 缺少文档是一个错误,请随时改进文档!

以上是关于将字符串文字限制为仅文本的主要内容,如果未能解决你的问题,请参考以下文章

将 kivy 的 TextInput 限制为仅 ascii 字符

如何将单个字符的 natvis 限制为仅 Visual Studio 中的字符

当类型为文本时,将输入框限制为仅数字

Android 可访问性将对讲限制为仅读取可见文本

将 iOS 中的 UIlabel 文本字段限制为两个字符,输入 3 个或更多时重置

如何将日期字段中的输入数据限制为仅限于某些字符?