我知道有一个 GHC 扩展,OverloadedStrings
它允许字符串文字(由 分隔"
)变得多态,类似于数字文字的内置行为。
我的问题是:是否有一个 GHC 扩展允许单字符文字(由 分隔'
)以类似的方式变得多态?
我知道有一个 GHC 扩展,OverloadedStrings
它允许字符串文字(由 分隔"
)变得多态,类似于数字文字的内置行为。
我的问题是:是否有一个 GHC 扩展允许单字符文字(由 分隔'
)以类似的方式变得多态?
不是从 GHC 8.8 开始,但您可以使用该QuasiQuotes
扩展来获得相当大的帮助。这是一个 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"
}
然后,您可以将其用作:
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|]
不。
让我通过对 GHC 源代码的一些探索来回答这个问题:
这是重命名器中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 ) }
您会看到对字符串有特殊处理,但对其他形式的文字没有。最后一个子句用于根据原始 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)) }
…</p>
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 }