Brandon Chinn pushed to branch wip/interpolated-strings at Glasgow Haskell Compiler / GHC
Commits:
-
a9f7a933
by Brandon Chinn at 2026-05-25T11:07:05-07:00
9 changed files:
- compiler/GHC/Builtin/Names.hs
- compiler/GHC/Rename/String.hs
- libraries/ghc-experimental/ghc-experimental.cabal.in
- + libraries/ghc-experimental/src/Data/String/Interpolate/Basic/Experimental.hs
- libraries/ghc-experimental/src/Data/String/Interpolate/Experimental.hs
- libraries/ghc-internal/src/GHC/Internal/Data/String/Interpolate.hs
- testsuite/tests/parser/should_run/StringInterpolationOverloaded.hs
- testsuite/tests/parser/should_run/StringInterpolationOverloaded.stdout
- testsuite/tests/qualified-strings/should_run/Example/SQL.hs
Changes:
| ... | ... | @@ -282,7 +282,11 @@ basicKnownKeyNames |
| 282 | 282 | fromStringName,
|
| 283 | 283 | |
| 284 | 284 | -- Interpolated strings
|
| 285 | - interpolateStringName,
|
|
| 285 | + interpolateRawName,
|
|
| 286 | + interpolateValueName,
|
|
| 287 | + interpolateAppendName,
|
|
| 288 | + interpolateEmptyName,
|
|
| 289 | + interpolateFinalizeName,
|
|
| 286 | 290 | |
| 287 | 291 | -- Enum stuff
|
| 288 | 292 | enumFromName, enumFromThenName,
|
| ... | ... | @@ -1090,8 +1094,17 @@ minusName = varQual gHC_INTERNAL_NUM (fsLit "-") minusClassOpK |
| 1090 | 1094 | negateName = varQual gHC_INTERNAL_NUM (fsLit "negate") negateClassOpKey
|
| 1091 | 1095 | |
| 1092 | 1096 | -- Module GHC.Internal.Data.String.Interpolate
|
| 1093 | -interpolateStringName :: Name
|
|
| 1094 | -interpolateStringName = varQual gHC_INTERNAL_DATA_STRING_INTERPOLATE (fsLit "interpolateString") interpolateStringKey
|
|
| 1097 | +interpolateRawName
|
|
| 1098 | + , interpolateValueName
|
|
| 1099 | + , interpolateAppendName
|
|
| 1100 | + , interpolateEmptyName
|
|
| 1101 | + , interpolateFinalizeName
|
|
| 1102 | + :: Name
|
|
| 1103 | +interpolateRawName = varQual gHC_INTERNAL_DATA_STRING_INTERPOLATE (fsLit "interpolateRaw" ) interpolateRawKey
|
|
| 1104 | +interpolateValueName = varQual gHC_INTERNAL_DATA_STRING_INTERPOLATE (fsLit "interpolateValue" ) interpolateValueKey
|
|
| 1105 | +interpolateAppendName = varQual gHC_INTERNAL_DATA_STRING_INTERPOLATE (fsLit "interpolateAppend" ) interpolateAppendKey
|
|
| 1106 | +interpolateEmptyName = varQual gHC_INTERNAL_DATA_STRING_INTERPOLATE (fsLit "interpolateEmpty" ) interpolateEmptyKey
|
|
| 1107 | +interpolateFinalizeName = varQual gHC_INTERNAL_DATA_STRING_INTERPOLATE (fsLit "interpolateFinalize") interpolateFinalizeKey
|
|
| 1095 | 1108 | |
| 1096 | 1109 | ---------------------------------
|
| 1097 | 1110 | -- ghc-bignum
|
| ... | ... | @@ -2392,8 +2405,17 @@ proxyHashKey :: Unique |
| 2392 | 2405 | proxyHashKey = mkPreludeMiscIdUnique 502
|
| 2393 | 2406 | |
| 2394 | 2407 | -- String interpolation
|
| 2395 | -interpolateStringKey :: Unique
|
|
| 2396 | -interpolateStringKey = mkPreludeMiscIdUnique 576
|
|
| 2408 | +interpolateRawKey
|
|
| 2409 | + , interpolateValueKey
|
|
| 2410 | + , interpolateAppendKey
|
|
| 2411 | + , interpolateEmptyKey
|
|
| 2412 | + , interpolateFinalizeKey
|
|
| 2413 | + :: Unique
|
|
| 2414 | +interpolateRawKey = mkPreludeMiscIdUnique 576
|
|
| 2415 | +interpolateValueKey = mkPreludeMiscIdUnique 577
|
|
| 2416 | +interpolateAppendKey = mkPreludeMiscIdUnique 578
|
|
| 2417 | +interpolateEmptyKey = mkPreludeMiscIdUnique 579
|
|
| 2418 | +interpolateFinalizeKey = mkPreludeMiscIdUnique 580
|
|
| 2397 | 2419 | |
| 2398 | 2420 | ---------------- Template Haskell -------------------
|
| 2399 | 2421 | -- GHC.Builtin.Names.TH: USES IdUniques 200-499
|
| ... | ... | @@ -8,14 +8,12 @@ import GHC.Prelude |
| 8 | 8 | |
| 9 | 9 | import Data.Maybe (isNothing)
|
| 10 | 10 | import qualified GHC.Builtin.Names as Builtin
|
| 11 | -import GHC.Builtin.Types (stringTyConName)
|
|
| 12 | 11 | import GHC.Data.StringMeta (StringMeta (..))
|
| 13 | 12 | import GHC.Hs
|
| 14 | 13 | import qualified GHC.LanguageExtensions as LangExt
|
| 15 | -import GHC.Rename.Env (lookupNameWithQualifier)
|
|
| 16 | -import GHC.Rename.Pat (rnOverLit)
|
|
| 14 | +import GHC.Rename.Env (lookupNameWithQualifier, lookupSyntaxName)
|
|
| 17 | 15 | import GHC.Tc.Utils.Monad
|
| 18 | -import GHC.Types.Name (mkVarOcc)
|
|
| 16 | +import GHC.Types.Name (Name)
|
|
| 19 | 17 | import GHC.Types.Name.Set (FreeNames, emptyFNs, plusFNs)
|
| 20 | 18 | import GHC.Types.SrcLoc (unLoc)
|
| 21 | 19 | |
| ... | ... | @@ -59,58 +57,46 @@ rewriteInterString :: |
| 59 | 57 | [HsInterStringPart GhcRn] ->
|
| 60 | 58 | RnM (HsExpr GhcRn, FreeNames)
|
| 61 | 59 | rewriteInterString meta parts = do
|
| 62 | - overloaded <- xoptM LangExt.OverloadedStrings
|
|
| 63 | - convertName <- newName (mkVarOcc "convert")
|
|
| 64 | - rawName <- newName (mkVarOcc "raw")
|
|
| 65 | - mappendName <- newName (mkVarOcc "mappend")
|
|
| 66 | - memptyName <- newName (mkVarOcc "mempty")
|
|
| 67 | - |
|
| 68 | - (interpolateStringName, fvs1) <-
|
|
| 69 | - case strMetaQualified meta of
|
|
| 70 | - Just modName -> lookupNameWithQualifier Builtin.interpolateStringName modName
|
|
| 71 | - Nothing -> pure (Builtin.interpolateStringName, emptyFNs)
|
|
| 72 | - (parts', fvs2) <- unzip <$> mapM (rewritePart overloaded convertName rawName) parts
|
|
| 60 | + mkOverloaded <- get_mkOverloaded
|
|
| 61 | + |
|
| 62 | + let lookupName' = lookupName (strMetaQualified meta)
|
|
| 63 | + (rawName, fns1) <- lookupName' Builtin.interpolateRawName
|
|
| 64 | + (convertName, fns2) <- lookupName' Builtin.interpolateValueName
|
|
| 65 | + (appendName, fns3) <- lookupName' Builtin.interpolateAppendName
|
|
| 66 | + (emptyName, fns4) <- lookupName' Builtin.interpolateEmptyName
|
|
| 67 | + (finalizeName, fns5) <- lookupName' Builtin.interpolateFinalizeName
|
|
| 68 | + |
|
| 73 | 69 | let expr =
|
| 74 | - (if not overloaded && isNothing (strMetaQualified meta) then addSig else id)
|
|
| 75 | - . nlHsApp (nlHsVar interpolateStringName)
|
|
| 76 | - . mkLam
|
|
| 77 | - [ nlVarPat convertName
|
|
| 78 | - , nlVarPat rawName
|
|
| 79 | - , nlVarPat mappendName
|
|
| 80 | - , nlVarPat memptyName
|
|
| 81 | - ]
|
|
| 82 | - $ foldr (\p acc -> nlHsApps mappendName [p, acc]) (nlHsVar memptyName) parts'
|
|
| 83 | - |
|
| 84 | - pure (unLoc expr, plusFNs $ [fvs1] ++ fvs2)
|
|
| 70 | + unLoc
|
|
| 71 | + . mkOverloaded
|
|
| 72 | + . nlHsApp (nlHsVar finalizeName)
|
|
| 73 | + . foldr (\p acc -> nlHsApps appendName [p, acc]) (nlHsVar emptyName)
|
|
| 74 | + $ map (rewritePart convertName rawName) parts
|
|
| 75 | + |
|
| 76 | + pure (expr, plusFNs [fns1, fns2, fns3, fns4, fns5])
|
|
| 85 | 77 | where
|
| 86 | - mkLam pats body = mkHsLam (noLocA pats) body
|
|
| 87 | - |
|
| 88 | - rewritePart overloaded convertName rawName = \case
|
|
| 89 | - HsInterStringRaw st s -> do
|
|
| 90 | - (lit, fvs) <- mkStringLit overloaded st s
|
|
| 91 | - pure (nlHsApps rawName [lit], fvs)
|
|
| 92 | - HsInterStringExpr _ e ->
|
|
| 93 | - pure (nlHsApps convertName [e], emptyFNs)
|
|
| 94 | - |
|
| 95 | - -- Add ":: String" to the given expression
|
|
| 96 | - addSig e =
|
|
| 97 | - noLocA . ExprWithTySig noExtField e $
|
|
| 98 | - HsWC
|
|
| 99 | - { hswc_ext = []
|
|
| 100 | - , hswc_body =
|
|
| 101 | - noLocA
|
|
| 102 | - HsSig
|
|
| 103 | - { sig_ext = noExtField
|
|
| 104 | - , sig_bndrs = HsOuterImplicit []
|
|
| 105 | - , sig_body = nlHsTyVar NotPromoted stringTyConName
|
|
| 106 | - }
|
|
| 107 | - }
|
|
| 108 | - |
|
| 109 | - mkStringLit overloaded st s = do
|
|
| 110 | - if overloaded
|
|
| 111 | - then do
|
|
| 112 | - -- FIXME(bchinn): allow -XRebindableSyntax -- lookupSyntaxName
|
|
| 113 | - (expr, fvs) <- rnOverLit noExtField $ OverLit noExtField (HsIsString st s)
|
|
| 114 | - pure (noLocA expr, fvs)
|
|
| 115 | - else
|
|
| 116 | - pure (nlHsLit $ HsString st s, emptyFNs) |
|
| 78 | + rewritePart convertName rawName = \case
|
|
| 79 | + HsInterStringRaw st s -> nlHsApps rawName [nlHsLit $ HsString st s]
|
|
| 80 | + HsInterStringExpr _ e -> nlHsApps convertName [e]
|
|
| 81 | + |
|
| 82 | + -- Handle -XOverloadedStrings
|
|
| 83 | + get_mkOverloaded = do
|
|
| 84 | + overloaded <- xoptM LangExt.OverloadedStrings
|
|
| 85 | + pure $
|
|
| 86 | + if overloaded && isNothing (strMetaQualified meta)
|
|
| 87 | + then nlHsApp (nlHsVar Builtin.fromStringName)
|
|
| 88 | + else id
|
|
| 89 | + |
|
| 90 | +-- | Look up the given name in the following places:
|
|
| 91 | +-- 1. If the given module is provided, in the module
|
|
| 92 | +-- 2. If -XRebindableSyntax, any name in scope
|
|
| 93 | +-- 3. Otherwise, return the built-in name.
|
|
| 94 | +lookupName :: Maybe ModuleName -> Name -> RnM (Name, FreeNames)
|
|
| 95 | +lookupName mQualMod name
|
|
| 96 | + | Just mod <- mQualMod =
|
|
| 97 | + lookupNameWithQualifier name mod
|
|
| 98 | + | otherwise = do
|
|
| 99 | + isRebindable <- xoptM LangExt.RebindableSyntax
|
|
| 100 | + if isRebindable
|
|
| 101 | + then lookupSyntaxName name
|
|
| 102 | + else pure (name, emptyFNs) |
| ... | ... | @@ -34,6 +34,7 @@ library |
| 34 | 34 | import: warnings
|
| 35 | 35 | exposed-modules:
|
| 36 | 36 | Data.String.Interpolate.Experimental
|
| 37 | + Data.String.Interpolate.Basic.Experimental
|
|
| 37 | 38 | Data.Sum.Experimental
|
| 38 | 39 | Data.Tuple.Experimental
|
| 39 | 40 | GHC.PrimOps
|
| 1 | +module Data.String.Interpolate.Basic.Experimental where
|
|
| 2 | + |
|
| 3 | +import Data.String (IsString (..))
|
|
| 4 | + |
|
| 5 | +interpolateRaw :: IsString s => String -> s
|
|
| 6 | +interpolateRaw = fromString
|
|
| 7 | + |
|
| 8 | +interpolateValue :: s -> s
|
|
| 9 | +interpolateValue = id
|
|
| 10 | + |
|
| 11 | +interpolateAppend :: Monoid s => s -> s -> s
|
|
| 12 | +interpolateAppend = mappend
|
|
| 13 | + |
|
| 14 | +interpolateEmpty :: Monoid s => s
|
|
| 15 | +interpolateEmpty = mempty
|
|
| 16 | + |
|
| 17 | +interpolateFinalize :: s -> s
|
|
| 18 | +interpolateFinalize = id |
| ... | ... | @@ -14,8 +14,13 @@ See the proposal for motivation and explanations: |
| 14 | 14 | https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0570-string-interpolation.rst
|
| 15 | 15 | -}
|
| 16 | 16 | module Data.String.Interpolate.Experimental (
|
| 17 | - SimpleStringInterpolator,
|
|
| 18 | - interpolateString,
|
|
| 17 | + interpolateRaw,
|
|
| 18 | + interpolateValue,
|
|
| 19 | + interpolateAppend,
|
|
| 20 | + interpolateEmpty,
|
|
| 21 | + interpolateFinalize,
|
|
| 22 | + |
|
| 23 | + -- * Interpolate class
|
|
| 19 | 24 | Interpolate (..),
|
| 20 | 25 | ) where
|
| 21 | 26 |
| ... | ... | @@ -12,57 +12,73 @@ |
| 12 | 12 | --
|
| 13 | 13 | -----------------------------------------------------------------------------
|
| 14 | 14 | {-# LANGUAGE CPP #-}
|
| 15 | +{-# LANGUAGE DefaultSignatures #-}
|
|
| 16 | +{-# LANGUAGE DerivingStrategies #-}
|
|
| 17 | +{-# LANGUAGE FlexibleContexts #-}
|
|
| 15 | 18 | {-# LANGUAGE FlexibleInstances #-}
|
| 19 | +{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
| 16 | 20 | {-# LANGUAGE RankNTypes #-}
|
| 21 | +{-# LANGUAGE TypeFamilies #-}
|
|
| 22 | +{-# LANGUAGE UndecidableSuperClasses #-}
|
|
| 17 | 23 | |
| 18 | 24 | module GHC.Internal.Data.String.Interpolate (
|
| 19 | - SimpleStringInterpolator,
|
|
| 20 | - interpolateString,
|
|
| 25 | + interpolateRaw,
|
|
| 26 | + interpolateValue,
|
|
| 27 | + interpolateAppend,
|
|
| 28 | + interpolateEmpty,
|
|
| 29 | + interpolateFinalize,
|
|
| 30 | + |
|
| 31 | + -- * StringBuilder
|
|
| 32 | + StringBuilder (..),
|
|
| 33 | + buildString,
|
|
| 34 | + |
|
| 35 | + -- * Interpolate class
|
|
| 21 | 36 | Interpolate (..),
|
| 22 | 37 | ) where
|
| 23 | 38 | |
| 24 | 39 | import GHC.Internal.Base
|
| 25 | -import GHC.Internal.Data.Maybe (Maybe (..))
|
|
| 40 | +import GHC.Internal.Data.Monoid (Endo (..))
|
|
| 26 | 41 | import GHC.Internal.Data.String (IsString, fromString)
|
| 27 | -import GHC.Internal.Show (ShowS, showChar, showString, shows)
|
|
| 42 | +import GHC.Internal.Show (show)
|
|
| 28 | 43 | import GHC.Internal.Types
|
| 29 | 44 | |
| 30 | -type SimpleStringInterpolator s =
|
|
| 31 | - ( forall ss.
|
|
| 32 | - (forall a. Interpolate a => a -> s)
|
|
| 33 | - -> (s -> s)
|
|
| 34 | - -> (s -> ss -> ss)
|
|
| 35 | - -> ss
|
|
| 36 | - -> ss
|
|
| 37 | - )
|
|
| 38 | - -> s
|
|
| 45 | +interpolateRaw :: String -> StringBuilder
|
|
| 46 | +interpolateRaw = fromString
|
|
| 39 | 47 | |
| 40 | -interpolateString :: (IsString s, Monoid s) => SimpleStringInterpolator s
|
|
| 41 | -interpolateString f = mconcat $ f (fromString . interpolate) id (:) []
|
|
| 42 | -{-# INLINE interpolateString #-}
|
|
| 48 | +interpolateValue :: Interpolate a => a -> StringBuilder
|
|
| 49 | +interpolateValue = interpolate
|
|
| 43 | 50 | |
| 44 | -class Interpolate a where
|
|
| 45 | - {-# MINIMAL interpolate | interpolateS #-}
|
|
| 51 | +interpolateAppend :: StringBuilder -> StringBuilder -> StringBuilder
|
|
| 52 | +interpolateAppend = mappend
|
|
| 46 | 53 | |
| 47 | - interpolate :: a -> String
|
|
| 48 | - interpolate x = interpolateS x ""
|
|
| 54 | +interpolateEmpty :: StringBuilder
|
|
| 55 | +interpolateEmpty = mempty
|
|
| 49 | 56 | |
| 50 | - interpolateS :: a -> ShowS
|
|
| 51 | - interpolateS x s = interpolate x <> s
|
|
| 57 | +interpolateFinalize :: StringBuilder -> String
|
|
| 58 | +interpolateFinalize = buildString
|
|
| 52 | 59 | |
| 53 | -instance Interpolate String where
|
|
| 54 | - interpolateS = showString
|
|
| 55 | -instance Interpolate Char where
|
|
| 56 | - interpolateS = showChar
|
|
| 60 | +{----- StringBuilder -----}
|
|
| 61 | + |
|
| 62 | +newtype StringBuilder = StringBuilder (Endo String)
|
|
| 63 | + deriving newtype (Semigroup, Monoid)
|
|
| 64 | +instance IsString StringBuilder where
|
|
| 65 | + fromString s = StringBuilder (Endo (s <>))
|
|
| 57 | 66 | |
| 58 | -#define INTERPOLATE_WITH_SHOW(x) \
|
|
| 59 | - instance Interpolate x where \
|
|
| 60 | - interpolateS = shows
|
|
| 61 | -INTERPOLATE_WITH_SHOW(Int)
|
|
| 62 | -INTERPOLATE_WITH_SHOW(Double)
|
|
| 63 | -INTERPOLATE_WITH_SHOW(Bool)
|
|
| 64 | --- FIXME(bchinn): More instances
|
|
| 67 | +buildString :: StringBuilder -> String
|
|
| 68 | +buildString (StringBuilder (Endo f)) = f ""
|
|
| 65 | 69 | |
| 66 | -instance Interpolate a => Interpolate (Maybe a) where
|
|
| 67 | - interpolateS Nothing = showString "Nothing"
|
|
| 68 | - interpolateS (Just a) = showString "Just (" . interpolateS a . showChar ')' |
|
| 70 | +{---- Interpolate ----}
|
|
| 71 | + |
|
| 72 | +class Interpolate a where
|
|
| 73 | + interpolate :: (IsString s, Monoid s) => a -> s
|
|
| 74 | + |
|
| 75 | +instance Interpolate String where
|
|
| 76 | + interpolate = fromString
|
|
| 77 | +instance Interpolate Char where
|
|
| 78 | + interpolate c = fromString [c]
|
|
| 79 | +instance Interpolate Int where
|
|
| 80 | + interpolate = interpolate . show
|
|
| 81 | +instance Interpolate Double where
|
|
| 82 | + interpolate = interpolate . show
|
|
| 83 | +instance Interpolate Bool where
|
|
| 84 | + interpolate = interpolate . show |
| ... | ... | @@ -2,10 +2,15 @@ |
| 2 | 2 | {-# LANGUAGE OverloadedStrings #-}
|
| 3 | 3 | {-# LANGUAGE RecordWildCards #-}
|
| 4 | 4 | {-# LANGUAGE StringInterpolation #-}
|
| 5 | +{-# LANGUAGE TypeFamilies #-}
|
|
| 5 | 6 | |
| 6 | 7 | import Data.String.Interpolate.Experimental
|
| 7 | 8 | import Data.Text (Text)
|
| 8 | 9 | import Data.Text qualified as Text
|
| 10 | +import Data.Text.Lazy.Builder qualified as LazyText
|
|
| 11 | +import Data.Text.Lazy.Builder.Int qualified as LazyText
|
|
| 12 | +import Data.Text.Lazy.Builder.RealFloat qualified as LazyText
|
|
| 13 | +import Data.Text.Lazy qualified as LazyText
|
|
| 9 | 14 | |
| 10 | 15 | main :: IO ()
|
| 11 | 16 | main = mapM_ runTest allTests
|
| ... | ... | @@ -30,14 +35,14 @@ allTests = |
| 30 | 35 | [ TestCase -- Text
|
| 31 | 36 | { label =
|
| 32 | 37 | """
|
| 33 | - let s = "world"; x = True in s <> s" hello ${s} ${x}" :: Text
|
|
| 38 | + let s = "world" :: Text; x = True in s <> s" hello ${s} ${x}" :: Text
|
|
| 34 | 39 | """
|
| 35 | 40 | , expression =
|
| 36 | - let s = "world"; x = True in s <> s" hello ${s} ${x}" :: Text
|
|
| 41 | + let s = "world" :: Text; x = True in s <> s" hello ${s} ${x}" :: Text
|
|
| 37 | 42 | }
|
| 38 | 43 | -- FIXME(bchinn): overloaded interpolated multiline string
|
| 39 | 44 | ]
|
| 40 | 45 | |
| 41 | 46 | -- Remove when text provides this instance
|
| 42 | 47 | instance Interpolate Text where
|
| 43 | - interpolateS = interpolateS . Text.unpack |
|
| 48 | + interpolate = interpolate . Text.unpack |
| 1 | 1 | ****************************************
|
| 2 | 2 | Input:
|
| 3 | - let s = "world"; x = True in s <> s" hello ${s} ${x}" :: Text
|
|
| 3 | + let s = "world" :: Text; x = True in s <> s" hello ${s} ${x}" :: Text
|
|
| 4 | 4 | ====>
|
| 5 | 5 | "world hello world True" |
| 1 | 1 | module Example.SQL (
|
| 2 | 2 | SqlQuery (..),
|
| 3 | 3 | SqlValue (..),
|
| 4 | - interpolateString,
|
|
| 4 | + |
|
| 5 | + -- * String interpolation
|
|
| 6 | + interpolateRaw,
|
|
| 7 | + interpolateValue,
|
|
| 8 | + interpolateAppend,
|
|
| 9 | + interpolateEmpty,
|
|
| 10 | + interpolateFinalize,
|
|
| 5 | 11 | ) where
|
| 6 | 12 | |
| 7 | 13 | import Data.String (IsString (..))
|
| ... | ... | @@ -41,12 +47,17 @@ instance ToSqlQuery String where |
| 41 | 47 | instance ToSqlQuery Int where
|
| 42 | 48 | toSqlQuery x = SqlQuery{sqlText = "?", sqlValues = [SqlInt x]}
|
| 43 | 49 | |
| 44 | -interpolateString ::
|
|
| 45 | - ( (forall a. ToSqlQuery a => a -> SqlQuery) ->
|
|
| 46 | - (String -> SqlQuery) ->
|
|
| 47 | - (SqlQuery -> SqlQuery -> SqlQuery) ->
|
|
| 48 | - SqlQuery ->
|
|
| 49 | - SqlQuery
|
|
| 50 | - ) ->
|
|
| 51 | - SqlQuery
|
|
| 52 | -interpolateString f = f toSqlQuery fromString (<>) mempty |
|
| 50 | +interpolateRaw :: String -> SqlQuery
|
|
| 51 | +interpolateRaw = fromString
|
|
| 52 | + |
|
| 53 | +interpolateValue :: ToSqlQuery a => a -> SqlQuery
|
|
| 54 | +interpolateValue = toSqlQuery
|
|
| 55 | + |
|
| 56 | +interpolateAppend :: SqlQuery -> SqlQuery -> SqlQuery
|
|
| 57 | +interpolateAppend = mappend
|
|
| 58 | + |
|
| 59 | +interpolateEmpty :: SqlQuery
|
|
| 60 | +interpolateEmpty = mempty
|
|
| 61 | + |
|
| 62 | +interpolateFinalize :: SqlQuery -> SqlQuery
|
|
| 63 | +interpolateFinalize = id |