diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,13 @@
 # Revision history for greskell
 
+## 2.0.3.3  -- 2025-01-30
+
+* Binder: now `newBind` produces an expression like `((__v0))`, that is, a variable name wrapped with double parens.
+  (see https://github.com/debug-ito/greskell/issues/18 )
+  While this is basically backward-compatible, it can break a user code if it depends on the internal of the `Greskell` returned by `newBind`.
+* Support ghc-9.12 (base-4.21).
+  
+
 ## 2.0.3.2  -- 2024-11-05
 
 * Bump dependency version bounds.
diff --git a/greskell.cabal b/greskell.cabal
--- a/greskell.cabal
+++ b/greskell.cabal
@@ -1,5 +1,5 @@
 name:                   greskell
-version:                2.0.3.2
+version:                2.0.3.3
 author:                 Toshio Ito <debug.ito@gmail.com>
 maintainer:             Toshio Ito <debug.ito@gmail.com>
 license:                BSD3
@@ -40,7 +40,7 @@
                         Data.Greskell.NonEmptyLike,
                         Data.Greskell.Logic
   -- other-modules:        
-  build-depends:        base ^>=4.13.0 || ^>=4.14.0 || ^>=4.15.0 || ^>=4.16.0 || ^>=4.17.0 || ^>=4.18.0 || ^>=4.19.0 || ^>=4.20.0,
+  build-depends:        base ^>=4.13.0 || ^>=4.14.0 || ^>=4.15.0 || ^>=4.16.0 || ^>=4.17.0 || ^>=4.18.0 || ^>=4.19.0 || ^>=4.20.0 || ^>=4.21.0,
                         greskell-core ^>=1.0.0,
                         text ^>=1.2.3 || ^>=2.0.2 || ^>=2.1,
                         transformers ^>=0.5.6 || ^>=0.6.1,
@@ -69,7 +69,7 @@
                         Data.Greskell.LogicSpec,
                         ExamplesSpec
   build-tool-depends:   hspec-discover:hspec-discover
-  build-depends:        base ^>=4.13.0 || ^>=4.14.0 || ^>=4.15.0 || ^>=4.16.0 || ^>=4.17.0 || ^>=4.18.0 || ^>=4.19.0 || ^>=4.20.0,
+  build-depends:        base ^>=4.13.0 || ^>=4.14.0 || ^>=4.15.0 || ^>=4.16.0 || ^>=4.17.0 || ^>=4.18.0 || ^>=4.19.0 || ^>=4.20.0 || ^>=4.21.0,
                         text ^>=1.2.3 || ^>=2.0.2 || ^>=2.1,
                         aeson ^>=2.0.2 || ^>=2.1.0 || ^>=2.2.3,
                         unordered-containers ^>=0.2.15,
@@ -84,7 +84,7 @@
   hs-source-dirs:       test
   ghc-options:          -Wall -fno-warn-unused-imports "-with-rtsopts=-M512m"
   main-is:              Typecheck.hs
-  build-depends:        base ^>=4.13.0 || ^>=4.14.0 || ^>=4.15.0 || ^>=4.16.0 || ^>=4.17.0 || ^>=4.18.0 || ^>=4.19.0 || ^>=4.20.0,
+  build-depends:        base ^>=4.13.0 || ^>=4.14.0 || ^>=4.15.0 || ^>=4.16.0 || ^>=4.17.0 || ^>=4.18.0 || ^>=4.19.0 || ^>=4.20.0 || ^>=4.21.0,
                         hspec ^>=2.9.1 || ^>=2.10.6 || ^>=2.11.9,
                         greskell,
                         should-not-typecheck ^>=2.1.0
@@ -104,7 +104,7 @@
   other-modules:        ServerTest.Common
   if flag(server-test)
     -- Explicitly remove dependency. See https://github.com/haskell/cabal/issues/1725
-    build-depends:        base ^>=4.13.0 || ^>=4.14.0 || ^>=4.15.0 || ^>=4.16.0 || ^>=4.17.0 || ^>=4.18.0 || ^>=4.19.0 || ^>=4.20.0,
+    build-depends:        base ^>=4.13.0 || ^>=4.14.0 || ^>=4.15.0 || ^>=4.16.0 || ^>=4.17.0 || ^>=4.18.0 || ^>=4.19.0 || ^>=4.20.0 || ^>=4.21.0,
                           aeson ^>=2.0.2 || ^>=2.1.0 || ^>=2.2.3,
                           hspec ^>=2.9.1 || ^>=2.10.6 || ^>=2.11.9,
                           text ^>=1.2.3 || ^>=2.0.2 || ^>=2.1,
@@ -135,7 +135,7 @@
   other-extensions:     OverloadedStrings
   other-modules:        ServerTest.Common
   if flag(server-behavior-test)
-    build-depends:        base ^>=4.13.0 || ^>=4.14.0 || ^>=4.15.0 || ^>=4.16.0 || ^>=4.17.0 || ^>=4.18.0 || ^>=4.19.0 || ^>=4.20.0,
+    build-depends:        base ^>=4.13.0 || ^>=4.14.0 || ^>=4.15.0 || ^>=4.16.0 || ^>=4.17.0 || ^>=4.18.0 || ^>=4.19.0 || ^>=4.20.0 || ^>=4.21.0,
                           aeson ^>=2.0.2 || ^>=2.1.0 || ^>=2.2.3,
                           hspec ^>=2.9.1 || ^>=2.10.6 || ^>=2.11.9,
                           text ^>=1.2.3 || ^>=2.0.2 || ^>=2.1,
diff --git a/src/Data/Greskell/Binder.hs b/src/Data/Greskell/Binder.hs
--- a/src/Data/Greskell/Binder.hs
+++ b/src/Data/Greskell/Binder.hs
@@ -88,7 +88,11 @@
 -- Unsafely create a placeholder variable of arbitrary type with the
 -- given index.
 unsafePlaceHolder :: PlaceHolderIndex -> Greskell a
-unsafePlaceHolder = unsafeGreskellLazy . toPlaceHolderVariable
+unsafePlaceHolder = unsafeGreskellLazy . wrapWithParens  . toPlaceHolderVariable
+  where
+    wrapWithParens v = "((" <> v <> "))"
+    -- This is necessary to ensure the v is always treated as a varible name (NOT a type name) in Groovy script.
+    -- See https://github.com/debug-ito/greskell/issues/18
 
 -- | __This function is only for internal use.__
 --
diff --git a/src/Data/Greskell/Extra.hs b/src/Data/Greskell/Extra.hs
--- a/src/Data/Greskell/Extra.hs
+++ b/src/Data/Greskell/Extra.hs
@@ -125,21 +125,21 @@
     for_writePropertyKeyValues =
       let binder = (writePropertyKeyValues [("age", (21 :: Int))] :: Binder (Walk SideEffect AVertex AVertex))
           (walk, binding) = runBinder binder
-      in [ (unpack $ toGremlin walk, "__.property(\"age\",__v0).identity()")
+      in [ (unpack $ toGremlin walk, "__.property(\"age\",((__v0))).identity()")
          , (show $ sortBy (comparing fst) $ KeyMap.toList binding, "[(\"__v0\",Number 21.0)]")
          ]
     for_writeKeyValues =
       let keyAge = ("age" :: Key AVertex Int)
           keyName = ("name" :: Key AVertex Text)
           (walk, binding) = runBinder $ writeKeyValues <$> sequence [keyAge <=:> 21, keyName <=:> "Josh"]
-      in [ (unpack $ toGremlin walk, "__.property(\"age\",__v0).property(\"name\",__v1).identity()")
+      in [ (unpack $ toGremlin walk, "__.property(\"age\",((__v0))).property(\"name\",((__v1))).identity()")
          , (show $ sortBy (comparing fst) $ KeyMap.toList binding, "[(\"__v0\",Number 21.0),(\"__v1\",String \"Josh\")]")
          ]
     for_operators =
       let keyNName = ("nickname" :: Key AVertex (Maybe Text))
           keyCompany = ("company" :: Key AVertex (Maybe Text))
           (walk, binding) = runBinder $ writeKeyValues <$> sequence [keyNName <=?> Nothing, keyCompany <=?> Just "foobar.com"]
-      in [ (unpack $ toGremlin walk, "__.property(\"company\",__v0).identity()")
+      in [ (unpack $ toGremlin walk, "__.property(\"company\",((__v0))).identity()")
          , (show $ sortBy (comparing fst) $ KeyMap.toList binding, "[(\"__v0\",String \"foobar.com\")]")
          ]
     for_gWhenEmptyInput =
diff --git a/test/Data/Greskell/BinderSpec.hs b/test/Data/Greskell/BinderSpec.hs
--- a/test/Data/Greskell/BinderSpec.hs
+++ b/test/Data/Greskell/BinderSpec.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE OverloadedStrings #-}
 module Data.Greskell.BinderSpec
     ( main
     , spec
@@ -8,7 +9,8 @@
 import           Data.Aeson             (toJSON)
 import qualified Data.Aeson.Key         as Key
 import qualified Data.Aeson.KeyMap      as KM
-import           Data.Text              (unpack)
+import           Data.Text              (Text)
+import qualified Data.Text              as T
 import           Test.Hspec
 
 import           Data.Greskell.AsLabel  (AsLabel)
@@ -18,50 +20,57 @@
 main :: IO ()
 main = hspec spec
 
-shouldBeVariable :: Greskell a -> IO ()
-shouldBeVariable got_greskell =
-  case unpack $ toGremlin got_greskell of
-   [] -> expectationFailure "Expect a Gremlin variable, but got empty script."
-   (h : rest) -> do
-     h `shouldSatisfy` (`elem` variableHeads)
-     forM_ rest (`shouldSatisfy` (`elem` variableRests))
+extractVarName :: Greskell a -> IO Text
+extractVarName got_greskell = checkVarName =<< (stripParens $ toGremlin got_greskell)
   where
+    stripParens v =
+      case T.stripPrefix "((" =<< T.stripSuffix "))" v of
+        Nothing -> do
+          expectationFailure "Binder should produce an expression of a variable wrapped with double parens"
+          return ""
+        Just a  -> return a
+    checkVarName v =
+      case T.unpack v of
+        [] -> do
+          expectationFailure "Expect a Gremlin variable, but got empty script."
+          return ""
+        (h : rest) -> do
+          h `shouldSatisfy` (`elem` variableHeads)
+          forM_ rest (`shouldSatisfy` (`elem` variableRests))
+          return v
     variableHeads = '_' : (['a' .. 'z'] ++ ['A' .. 'Z'])
     variableRests = variableHeads ++ ['0' .. '9']
 
-toKey :: Greskell a -> Key.Key
-toKey = Key.fromText . toGremlin
-
 spec :: Spec
 spec = describe "Binder" $ do
   it "should keep bound values" $ do
     let b = do
           v1 <- newBind (100 :: Int)
-          v2 <- newBind "hogehoge"
+          v2 <- newBind ("hogehoge" :: Text)
           return (v1, v2)
         ((got_v1, got_v2), got_bind) = runBinder b
     toGremlin got_v1 `shouldNotBe` toGremlin got_v2
-    shouldBeVariable got_v1
-    shouldBeVariable got_v2
-    got_bind `shouldBe` KM.fromList [ (toKey got_v1, toJSON (100 :: Int)),
-                                      (toKey got_v2, toJSON "hogehoge")
+    v1Name <- extractVarName got_v1
+    v2Name <- extractVarName got_v2
+    got_bind `shouldBe` KM.fromList [ (Key.fromText v1Name, toJSON (100 :: Int)),
+                                      (Key.fromText v2Name, toJSON ("hogehoge" :: Text))
                                     ]
   it "should compose and produce new variables" $ do
-    let b = newBind "foobar"
+    let b = newBind ("foobar" :: Text)
         ((got_v1, got_v2), got_bind) = runBinder $ ((,) <$> b <*> b)
     toGremlin got_v1 `shouldNotBe` toGremlin got_v2
-    shouldBeVariable got_v1
-    shouldBeVariable got_v2
-    got_bind `shouldBe` KM.fromList [ (toKey got_v1, toJSON "foobar"),
-                                      (toKey got_v2, toJSON "foobar")
+    v1Name <- extractVarName got_v1
+    v2Name <- extractVarName got_v2
+    got_bind `shouldBe` KM.fromList [ (Key.fromText v1Name, toJSON ("foobar" :: Text)),
+                                      (Key.fromText v2Name, toJSON ("foobar" :: Text))
                                     ]
   it "should also be able to produce AsLabels" $ do
     let newIntLabel :: Binder (AsLabel Int)
         newIntLabel = newAsLabel
-        newVar = newBind "foobar"
+        newVar = newBind ("foobar" :: Text)
         ((got_v1, got_l1, got_v2, got_l2), _) =
           runBinder $ ((,,,) <$> newVar <*> newIntLabel <*> newVar <*> newIntLabel)
-    shouldBeVariable got_v1
-    shouldBeVariable got_v2
+    _ <- extractVarName got_v1
+    _ <- extractVarName got_v2
     toGremlin got_v1 `shouldNotBe` toGremlin got_v2
     got_l1 `shouldNotBe` got_l2
diff --git a/test/Data/Greskell/ExtraSpec.hs b/test/Data/Greskell/ExtraSpec.hs
--- a/test/Data/Greskell/ExtraSpec.hs
+++ b/test/Data/Greskell/ExtraSpec.hs
@@ -35,15 +35,15 @@
       let input :: [(Text, Int)]
           input = [("age", 24)]
       (runBoundWalk $ writePropertyKeyValues input)
-        `shouldBe` ( "__.property(\"age\",__v0).identity()",
+        `shouldBe` ( "__.property(\"age\",((__v0))).identity()",
                      KM.fromList [("__v0", Number 24)]
                    )
     specify "multiple props" $ do
       let input :: [(Text, Value)]
           input = [("age", Number 24), ("name", String "Toshio"), ("foo", String "bar")]
       (runBoundWalk $ writePropertyKeyValues input)
-        `shouldBe` ( "__.property(\"age\",__v0).property(\"name\",__v1)"
-                     <> ".property(\"foo\",__v2).identity()",
+        `shouldBe` ( "__.property(\"age\",((__v0))).property(\"name\",((__v1)))"
+                     <> ".property(\"foo\",((__v2))).identity()",
                      KM.fromList [ ("__v0", Number 24),
                                    ("__v1", String "Toshio"),
                                    ("__v2", String "bar")
diff --git a/test/ServerTest.hs b/test/ServerTest.hs
--- a/test/ServerTest.hs
+++ b/test/ServerTest.hs
@@ -23,7 +23,7 @@
 import           Data.Greskell.AsIterator          (AsIterator (IteratorItem))
 import           Data.Greskell.AsLabel             (AsLabel (..), lookupAsM)
 import qualified Data.Greskell.AsLabel             as As
-import           Data.Greskell.Binder              (newBind, runBinder)
+import           Data.Greskell.Binder              (Binder, newBind, runBinder)
 import           Data.Greskell.Extra               (gWhenEmptyInput)
 import           Data.Greskell.GMap                (GMapEntry, unGMapEntry)
 import           Data.Greskell.Graph               (AEdge (..), AProperty (..), AVertex (..),
@@ -33,8 +33,8 @@
                                                     (=:))
 import           Data.Greskell.GraphSON            (FromGraphSON, GValue, nonTypedGValue,
                                                     parseEither)
-import           Data.Greskell.Gremlin             (Order, P, Predicate (..), cCompare, oDecr,
-                                                    oIncr, pAnd, pEq, pGte, pLt, pNot, pTest)
+import           Data.Greskell.Gremlin             (Order, P, Predicate (..), cCompare, oAsc, oDesc,
+                                                    pAnd, pEq, pGte, pLt, pNot, pTest)
 import           Data.Greskell.Greskell            (Greskell, ToGreskell (..), false, gvalueInt,
                                                     list, number, single, toGremlin, toGreskell,
                                                     true, unsafeGreskell, unsafeMethodCall, value)
@@ -60,6 +60,7 @@
 spec :: Spec
 spec = withEnv $ do
   spec_basics
+  spec_binder
   spec_comparator
   spec_predicate
   spec_T
@@ -155,19 +156,34 @@
          => Greskell a -> b -> SpecWith (String, Int)
 checkOne input expected = checkRaw input [expected]
 
+checkBinder :: (AsIterator a, b ~ IteratorItem a, FromGraphSON b, Eq b, Show b)
+            => [b] -> Binder (Greskell a) -> SpecWith (String, Int)
+checkBinder expected binder = specify label $ withClient $ \client -> do
+  got <- WS.slurpResults =<< WS.submit client script (Just binding)
+  got `shouldBe` V.fromList expected
+  where
+    (script, binding) = runBinder binder
+    label = (unpack $ toGremlin script) ++ " with " ++ show binding
 
+spec_binder :: SpecWith (String, Int)
+spec_binder = describe "server and Binder" $ do
+  checkBinder [100 :: Int] $ newBind (100 :: Int)
+  checkBinder [110 :: Int] $ do
+    b <- newBind (100 :: Int)
+    return $ b + (10 :: Greskell Int)
+
 spec_comparator :: SpecWith (String,Int)
 spec_comparator = do
-  let oIncr' :: Greskell (Order Int)
-      oIncr' = oIncr
-      oDecr' :: Greskell (Order Int)
-      oDecr' = oDecr
-  checkOne (cCompare oIncr' 20 20) 0
-  checkOne (cCompare oIncr' 10 20) (-1)
-  checkOne (cCompare oIncr' 20 10) 1
-  checkOne (cCompare oDecr' 20 20) 0
-  checkOne (cCompare oDecr' 10 20) 1
-  checkOne (cCompare oDecr' 20 10) (-1)
+  let oAsc' :: Greskell (Order Int)
+      oAsc' = oAsc
+      oDesc' :: Greskell (Order Int)
+      oDesc' = oDesc
+  checkOne (cCompare oAsc' 20 20) 0
+  checkOne (cCompare oAsc' 10 20) (-1)
+  checkOne (cCompare oAsc' 20 10) 1
+  checkOne (cCompare oDesc' 20 20) 0
+  checkOne (cCompare oDesc' 10 20) 1
+  checkOne (cCompare oDesc' 20 10) (-1)
 
 spec_predicate :: SpecWith (String,Int)
 spec_predicate = do
