简体   繁体   English

是否有用于启用重载字符文字的 GHC 扩展?

[英]Is there a GHC extension for enabling overloaded character literals?

I am aware that there is a GHC extension, OverloadedStrings , which allows string literals (delimited by " ) to become polymorphic, similar to the built-in behavior for number literals.我知道有一个 GHC 扩展OverloadedStrings ,它允许字符串文字(由"分隔)变得多态,类似于数字文字的内置行为。

My question is: is there a GHC extension that allows single character literals (delimited by ' ) to become polymorphic in an analogous way?我的问题是:是否有一个 GHC 扩展允许单字符文字(由'分隔)以类似的方式变得多态?

Not as of GHC 8.8, but you can use the QuasiQuotes extension to get pretty far.不是从 GHC 8.8 开始,但您可以使用QuasiQuotes扩展来获得相当远的效果。 Here is an example of a quasiquote which only accepts an ascii character and converts it to its byte representation.这是一个 quasiquote 的示例,它只接受一个 ascii 字符并将其转换为它的字节表示。

import Language.Haskell.TH
import Language.Haskell.TH.Quote
import Language.Haskell.TH.Syntax

import Data.Word (Word8)
import Data.Char (isAscii)

asciiByte :: QuasiQuoter
asciiByte = QuasiQuoter
  { quoteExp = \str -> case str of
                         [c] | isAscii c -> lift (fromIntegral (fromEnum c) :: Word8)
                         _ -> fail ("asciiByte: expects a single ascii character, got " ++ str) 
  , quotePat = \_ -> fail "asciiByte: only available for expressions"
  , quoteType = \_ -> fail "asciiByte: only available for expressions"
  , quoteDec = \_ -> fail "asciiByte: only available for expressions"
  }

Then, you can use it as:然后,您可以将其用作:

ghci> [asciiByte|a|]
97
ghci> [asciiByte|é|]

<interactive>:75:12: error:
    • asciiByte: expects a single ascii character, got é
    • In the quasi-quotation: [asciiByte|é|]
ghci> [asciiByte|abc|]

<interactive>:76:12: error:
    • asciiByte: expects a single ascii character, got abc
    • In the quasi-quotation: [asciiByte|abc|]

No.不。

Let me answer that with some exploration of the GHC source code:让我通过对 GHC 源代码的一些探索来回答这个问题:

This is the code in the renamer where OverloadedString take effect:这是重命名器中OverloadedString生效的代码:

rnExpr (HsLit x lit@(HsString src s))
  = do { opt_OverloadedStrings <- xoptM LangExt.OverloadedStrings
       ; if opt_OverloadedStrings then
            rnExpr (HsOverLit x (mkHsIsString src s))
         else do {
            ; rnLit lit
            ; return (HsLit x (convertLit lit), emptyFVs) } }

rnExpr (HsLit x lit)
  = do { rnLit lit
       ; return (HsLit x(convertLit lit), emptyFVs) }

rnExpr (HsOverLit x lit)
  = do { ((lit', mb_neg), fvs) <- rnOverLit lit -- See Note [Negative zero]
       ; case mb_neg of
              Nothing -> return (HsOverLit x lit', fvs)
              Just neg -> return (HsApp x (noLoc neg) (noLoc (HsOverLit x lit'))
                                 , fvs ) }

( https://github.com/ghc/ghc/blob/c2991f16cb6f5b4e7cff46a394dda4247d973f44/compiler/rename/RnExpr.hs#L152 ) https://github.com/ghc/ghc/blob/c2991f16cb6f5b4e7cff46a394dda4247d973f44/compiler/rename/RnExpr.hs#L152

You see that there is special handling for strings, but not for other forms of literals.您会看到对字符串有特殊处理,但对于其他 forms 文字则没有。 The last clause is for literals that are overloaded according to the original Haskell standard, as we can see in these lines from the parser:最后一个子句用于根据原始 Haskell 标准重载的文字,正如我们在解析器的这些行中看到的那样:

        | literal                       { ECP $ mkHsLitPV $! $1 }
-- This will enable overloaded strings permanently.  Normally the renamer turns HsString
-- into HsOverLit when -foverloaded-strings is on.
--      | STRING    { sL (getLoc $1) (HsOverLit $! mkHsIsString (getSTRINGs $1)
--                                       (getSTRING $1) noExt) }
        | INTEGER   { ECP $ mkHsOverLitPV (sL1 $1 $ mkHsIntegral   (getINTEGER  $1)) }
        | RATIONAL  { ECP $ mkHsOverLitPV (sL1 $1 $ mkHsFractional (getRATIONAL $1)) }

( https://github.com/ghc/ghc/blob/c2991f16cb6f5b4e7cff46a394dda4247d973f44/compiler/parser/Parser.y#L2793 ) https://github.com/ghc/ghc/blob/c2991f16cb6f5b4e7cff46a394dda4247d973f44/compiler/parser/Parser.y#L2793

literal :: { Located (HsLit GhcPs) }
        : CHAR              { sL1 $1 $ HsChar       (getCHARs $1) $ getCHAR $1 }
        | STRING            { sL1 $1 $ HsString     (getSTRINGs $1)
                                                    $ getSTRING $1 }
        | PRIMINTEGER       { sL1 $1 $ HsIntPrim    (getPRIMINTEGERs $1)
                                                    $ getPRIMINTEGER $1 }
        | PRIMWORD          { sL1 $1 $ HsWordPrim   (getPRIMWORDs $1)
                                                    $ getPRIMWORD $1 }
        | PRIMCHAR          { sL1 $1 $ HsCharPrim   (getPRIMCHARs $1)
                                                    $ getPRIMCHAR $1 }
        | PRIMSTRING        { sL1 $1 $ HsStringPrim (getPRIMSTRINGs $1)
                                                    $ getPRIMSTRING $1 }
        | PRIMFLOAT         { sL1 $1 $ HsFloatPrim  noExt $ getPRIMFLOAT $1 }
        | PRIMDOUBLE        { sL1 $1 $ HsDoublePrim noExt $ getPRIMDOUBLE $1 }

( https://github.com/ghc/ghc/blob/c2991f16cb6f5b4e7cff46a394dda4247d973f44/compiler/parser/Parser.y#L3708 ) https://github.com/ghc/ghc/blob/c2991f16cb6f5b4e7cff46a394dda4247d973f44/compiler/parser/Parser.y#L3708

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM