packages feed

greskell 0.2.1.1 → 0.2.2.0

raw patch · 8 files changed

+301/−16 lines, 8 filesdep +exceptionsdep ~hintPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: exceptions

Dependency ranges changed: hint

API changes (from Hackage documentation)

+ Data.Greskell.AsLabel: AsLabel :: Text -> AsLabel a
+ Data.Greskell.AsLabel: NoSuchAsLabel :: AsLookupException
+ Data.Greskell.AsLabel: ParseError :: String -> AsLookupException
+ Data.Greskell.AsLabel: [unAsLabel] :: AsLabel a -> Text
+ Data.Greskell.AsLabel: data AsLookupException
+ Data.Greskell.AsLabel: data SelectedMap a
+ Data.Greskell.AsLabel: instance Data.Foldable.Foldable Data.Greskell.AsLabel.SelectedMap
+ Data.Greskell.AsLabel: instance Data.Greskell.GraphSON.FromGraphSON a => Data.Greskell.GraphSON.FromGraphSON (Data.Greskell.AsLabel.SelectedMap a)
+ Data.Greskell.AsLabel: instance Data.Greskell.GraphSON.GraphSONTyped.GraphSONTyped (Data.Greskell.AsLabel.SelectedMap a)
+ Data.Greskell.AsLabel: instance Data.Greskell.Greskell.ToGreskell (Data.Greskell.AsLabel.AsLabel a)
+ Data.Greskell.AsLabel: instance Data.Traversable.Traversable Data.Greskell.AsLabel.SelectedMap
+ Data.Greskell.AsLabel: instance GHC.Base.Functor Data.Greskell.AsLabel.AsLabel
+ Data.Greskell.AsLabel: instance GHC.Base.Functor Data.Greskell.AsLabel.SelectedMap
+ Data.Greskell.AsLabel: instance GHC.Classes.Eq (Data.Greskell.AsLabel.AsLabel a)
+ Data.Greskell.AsLabel: instance GHC.Classes.Eq Data.Greskell.AsLabel.AsLookupException
+ Data.Greskell.AsLabel: instance GHC.Classes.Eq a => GHC.Classes.Eq (Data.Greskell.AsLabel.SelectedMap a)
+ Data.Greskell.AsLabel: instance GHC.Classes.Ord (Data.Greskell.AsLabel.AsLabel a)
+ Data.Greskell.AsLabel: instance GHC.Classes.Ord Data.Greskell.AsLabel.AsLookupException
+ Data.Greskell.AsLabel: instance GHC.Exception.Type.Exception Data.Greskell.AsLabel.AsLookupException
+ Data.Greskell.AsLabel: instance GHC.Show.Show (Data.Greskell.AsLabel.AsLabel a)
+ Data.Greskell.AsLabel: instance GHC.Show.Show Data.Greskell.AsLabel.AsLookupException
+ Data.Greskell.AsLabel: instance GHC.Show.Show a => GHC.Show.Show (Data.Greskell.AsLabel.SelectedMap a)
+ Data.Greskell.AsLabel: lookup :: AsLabel a -> SelectedMap b -> Maybe b
+ Data.Greskell.AsLabel: lookupAs :: FromGraphSON a => AsLabel a -> SelectedMap GValue -> Either AsLookupException a
+ Data.Greskell.AsLabel: lookupAsM :: (MonadThrow m, FromGraphSON a) => AsLabel a -> SelectedMap GValue -> m a
+ Data.Greskell.AsLabel: lookupM :: MonadThrow m => AsLabel a -> SelectedMap b -> m b
+ Data.Greskell.AsLabel: newtype AsLabel a
+ Data.Greskell.Binder: instance GHC.Classes.Eq Data.Greskell.Binder.BinderS
+ Data.Greskell.Binder: instance GHC.Show.Show Data.Greskell.Binder.BinderS
+ Data.Greskell.Binder: newAsLabel :: Binder (AsLabel a)
+ Data.Greskell.GTraversal: -- | The end type of the projection.
+ Data.Greskell.GTraversal: gAs :: AsLabel a -> Walk Transform a a
+ Data.Greskell.GTraversal: gInV :: (Edge e, Vertex v) => Walk Transform e v
+ Data.Greskell.GTraversal: gInV' :: Edge e => Walk Transform e AVertex
+ Data.Greskell.GTraversal: gOutV :: (Edge e, Vertex v) => Walk Transform e v
+ Data.Greskell.GTraversal: gOutV' :: Edge e => Walk Transform e AVertex
+ Data.Greskell.GTraversal: gSelect1 :: AsLabel a -> Walk Transform s a
+ Data.Greskell.GTraversal: gSelectBy1 :: AsLabel a -> ByProjection a b -> Walk Transform s b
+ Data.Greskell.GTraversal: gSelectByN :: AsLabel a -> AsLabel a -> [AsLabel a] -> ByProjection a b -> Walk Transform s (SelectedMap b)
+ Data.Greskell.GTraversal: gSelectN :: AsLabel a -> AsLabel b -> [AsLabel c] -> Walk Transform s (SelectedMap GValue)
+ Data.Greskell.Graph: -- <tt>e</tt> is an <a>Edge</a> or VertexProperty.
+ Data.Greskell.Graph: -- class. If you don't care, use <a>AVertexProperty</a> if type
+ Data.Greskell.Graph: -- implementation and its settings.
+ Data.Greskell.Graph: -- | ID type of the <a>Vertex</a> this edge connects.
- Data.Greskell.GTraversal: gFlatMap :: (ToGTraversal g) => g Transform s e -> Walk Transform s e
+ Data.Greskell.GTraversal: gFlatMap :: ToGTraversal g => g Transform s e -> Walk Transform s e
- Data.Greskell.GTraversal: gFrom :: (ToGTraversal g) => g Transform s e -> AddAnchor s e
+ Data.Greskell.GTraversal: gFrom :: ToGTraversal g => g Transform s e -> AddAnchor s e
- Data.Greskell.GTraversal: gHas1' :: (Element s) => Key s v -> Walk Filter s s
+ Data.Greskell.GTraversal: gHas1' :: Element s => Key s v -> Walk Filter s s
- Data.Greskell.GTraversal: gHas2' :: (Element s) => Key s v -> Greskell v -> Walk Filter s s
+ Data.Greskell.GTraversal: gHas2' :: Element s => Key s v -> Greskell v -> Walk Filter s s
- Data.Greskell.GTraversal: gHas2P' :: (Element s) => Key s v -> Greskell (P v) -> Walk Filter s s
+ Data.Greskell.GTraversal: gHas2P' :: Element s => Key s v -> Greskell (P v) -> Walk Filter s s
- Data.Greskell.GTraversal: gHasLabel' :: (Element s) => Greskell Text -> Walk Filter s s
+ Data.Greskell.GTraversal: gHasLabel' :: Element s => Greskell Text -> Walk Filter s s
- Data.Greskell.GTraversal: gIn' :: (Vertex v) => [Greskell Text] -> Walk Transform v AVertex
+ Data.Greskell.GTraversal: gIn' :: Vertex v => [Greskell Text] -> Walk Transform v AVertex
- Data.Greskell.GTraversal: gInE' :: (Vertex v) => [Greskell Text] -> Walk Transform v AEdge
+ Data.Greskell.GTraversal: gInE' :: Vertex v => [Greskell Text] -> Walk Transform v AEdge
- Data.Greskell.GTraversal: gOut' :: (Vertex v) => [Greskell Text] -> Walk Transform v AVertex
+ Data.Greskell.GTraversal: gOut' :: Vertex v => [Greskell Text] -> Walk Transform v AVertex
- Data.Greskell.GTraversal: gOutE' :: (Vertex v) => [Greskell Text] -> Walk Transform v AEdge
+ Data.Greskell.GTraversal: gOutE' :: Vertex v => [Greskell Text] -> Walk Transform v AEdge
- Data.Greskell.GTraversal: gTo :: (ToGTraversal g) => g Transform s e -> AddAnchor s e
+ Data.Greskell.GTraversal: gTo :: ToGTraversal g => g Transform s e -> AddAnchor s e
- Data.Greskell.GTraversal: modulateWith :: (WalkType c) => Walk c s e -> [Walk c e e] -> Walk c s e
+ Data.Greskell.GTraversal: modulateWith :: WalkType c => Walk c s e -> [Walk c e e] -> Walk c s e
- Data.Greskell.Gremlin: ComparatorA :: a -> a -> Int -> ComparatorA a
+ Data.Greskell.Gremlin: ComparatorA :: (a -> a -> Int) -> ComparatorA a
- Data.Greskell.Gremlin: PredicateA :: a -> Bool -> PredicateA a
+ Data.Greskell.Gremlin: PredicateA :: (a -> Bool) -> PredicateA a

Files

ChangeLog.md view
@@ -1,5 +1,20 @@ # Revision history for greskell +## 0.2.2.0  -- 2018-11-23++* Add new `AsLabel` module.++### GTraversal module++* Add `gAs`, `gSelect1`, `gSelectN`, `gSelectBy1`, `gSelectByN`,+  `gOutV`, `gOutV'`, `gInV`, `gInV'` functions.++### Binder module++* Add `newAsLabel` function.+++ ## 0.2.1.1  -- 2018-10-03  * Confirm test with `base-4.12.0.0`
greskell.cabal view
@@ -1,5 +1,5 @@ name:                   greskell-version:                0.2.1.1+version:                0.2.2.0 author:                 Toshio Ito <debug.ito@gmail.com> maintainer:             Toshio Ito <debug.ito@gmail.com> license:                BSD3@@ -31,7 +31,8 @@                         Data.Greskell.Gremlin,                         Data.Greskell.Binder,                         Data.Greskell.Graph,-                        Data.Greskell.GTraversal+                        Data.Greskell.GTraversal,+                        Data.Greskell.AsLabel   -- other-modules:           build-depends:        base >=4.9.0.0 && <4.13,                         greskell-core >=0.1.2.0 && <0.2,@@ -40,7 +41,8 @@                         aeson >=0.11.2.1 && <1.5,                         unordered-containers >=0.2.7.1 && <0.3,                         semigroups >=0.18.2 && <0.19,-                        vector >=0.12.0.1 && <0.13+                        vector >=0.12.0.1 && <0.13,+                        exceptions >=0.8.3 && <0.11  test-suite spec   type:                 exitcode-stdio-1.0@@ -87,7 +89,7 @@   main-is:              HintTest.hs   build-depends:        base, hspec,                         greskell, -                        hint >=0.6 && <0.9+                        hint >=0.6 && <0.10   flag server-test
src/Data/Greskell.hs view
@@ -14,7 +14,8 @@          module Data.Greskell.Graph,          module Data.Greskell.GraphSON,          module Data.Greskell.GMap,-         module Data.Greskell.AsIterator+         module Data.Greskell.AsIterator,+         module Data.Greskell.AsLabel        ) where  import Data.Greskell.Greskell@@ -25,3 +26,4 @@ import Data.Greskell.GraphSON import Data.Greskell.GMap import Data.Greskell.AsIterator+import Data.Greskell.AsLabel
+ src/Data/Greskell/AsLabel.hs view
@@ -0,0 +1,86 @@+{-# LANGUAGE OverloadedStrings, TypeFamilies, GeneralizedNewtypeDeriving, DeriveTraversable #-}+-- |+-- Module: Data.Greskell.AsLabel+-- Description: Label string used in .as step+-- Maintainer: Toshio Ito <debug.ito@gmail.com>+--+-- @since 0.2.2.0+module Data.Greskell.AsLabel+       ( AsLabel(..),+         SelectedMap,+         lookup,+         lookupM,+         lookupAs,+         lookupAsM,+         AsLookupException(..)+       ) where++import Prelude hiding (lookup)++import Control.Exception (Exception)+import Control.Monad.Catch (MonadThrow(..))+import Data.Foldable (Foldable)+import Data.HashMap.Strict (HashMap)+import qualified Data.HashMap.Strict as HM+import Data.Greskell.GraphSON (GValue, GraphSONTyped(..), FromGraphSON(..), parseEither)+import Data.Greskell.Greskell (ToGreskell(..))+import qualified Data.Greskell.Greskell as Greskell+import Data.Text (Text)+import Data.Traversable (Traversable)++-- | 'AsLabel' @a@ represents a label string used in @.as@ step+-- pointing to the data of type @a@.+newtype AsLabel a = AsLabel { unAsLabel :: Text }+               deriving (Show,Eq,Ord)++-- | Returns the 'Text' as a Gremlin string.+instance ToGreskell (AsLabel a) where+  type GreskellReturn (AsLabel a) = Text+  toGreskell (AsLabel t) = Greskell.string t++-- | Unsafely convert the phantom type.+instance Functor AsLabel where+  fmap _ (AsLabel t) = AsLabel t++-- | A map keyed with 'AsLabel'. Obtained from @.select@ step, for+-- example.+newtype SelectedMap a = SelectedMap (HashMap Text a)+                    deriving (Show,Eq,Functor,Foldable,Traversable)++instance GraphSONTyped (SelectedMap a) where+  gsonTypeFor _ = "g:Map"++instance FromGraphSON a => FromGraphSON (SelectedMap a) where+  parseGraphSON gv = fmap SelectedMap $ parseGraphSON gv++-- | An 'Exception' raised by 'lookupM' and 'lookupAsM'.+data AsLookupException = NoSuchAsLabel+                         -- ^ The 'SelectedMap' does not have the+                         -- given 'AsLabel' as the key.+                       | ParseError String+                         -- ^ Failed to parse the value into the type+                         -- that the 'AsLabel' indicates. The 'String'+                         -- is the error message.+                       deriving (Show,Eq,Ord)++instance Exception AsLookupException++-- | Get value from 'SelectedMap'.+lookup :: AsLabel a -> SelectedMap b -> Maybe b+lookup (AsLabel l) (SelectedMap m) = HM.lookup l m++-- | 'MonadThrow' version of 'lookup'. If there is no value for the+-- 'AsLabel', it throws 'NoSuchAsLabel'.+lookupM :: MonadThrow m => AsLabel a -> SelectedMap b -> m b+lookupM l m = maybe (throwM NoSuchAsLabel) return $ lookup l m++-- | Get value from 'SelectedMap' and parse the value into @a@.+lookupAs :: FromGraphSON a => AsLabel a -> SelectedMap GValue -> Either AsLookupException a+lookupAs l m =+  case lookup l m of+   Nothing -> Left NoSuchAsLabel+   Just gv -> either (Left . ParseError) Right $ parseEither gv++-- | 'MonadThrow' version of 'lookupAs'.+lookupAsM :: (MonadThrow m, FromGraphSON a) => AsLabel a -> SelectedMap GValue -> m a+lookupAsM l m = either throwM return $ lookupAs l m
src/Data/Greskell/Binder.hs view
@@ -11,6 +11,7 @@          Binding,          -- * Actions          newBind,+         newAsLabel,          -- * Runners          runBinder        ) where@@ -20,10 +21,29 @@ import Data.Aeson (Value, ToJSON(toJSON), Object) import Data.Monoid ((<>)) import qualified Data.HashMap.Strict as HM+import qualified Data.Text as T import qualified Data.Text.Lazy as TL +import Data.Greskell.AsLabel (AsLabel(..)) import Data.Greskell.Greskell (unsafeGreskellLazy, Greskell) +-- | State in the 'Binder'.+data BinderS =+  BinderS+  { varIndex :: PlaceHolderIndex,+    varBindings :: [Value],+    asLabelIndex :: PlaceHolderIndex+  }+  deriving (Show,Eq)++initBinderS :: BinderS+initBinderS =+  BinderS+  { varIndex = 0,+    varBindings = [],+    asLabelIndex = 0+  }+ -- $setup -- -- >>> import Control.Applicative ((<$>), (<*>))@@ -32,7 +52,7 @@ -- >>> import Data.Ord (comparing) -- >>> import qualified Data.HashMap.Strict as HashMap --- | A Monad that manages binding variables to values.+-- | A Monad that manages binding variables and labels to values. -- -- >>> let binder = (,) <$> newBind (10 :: Int) <*> newBind "hoge" -- >>> let ((var_int, var_str), binding) = runBinder binder@@ -42,7 +62,7 @@ -- "__v1" -- >>> sortBy (comparing fst) $ HashMap.toList binding -- [("__v0",Number 10.0),("__v1",String "hoge")]-newtype Binder a = Binder { unBinder :: State (PlaceHolderIndex, [Value]) a }+newtype Binder a = Binder { unBinder :: State BinderS a }                    deriving (Functor, Applicative, Monad)  -- | Binding between Gremlin variable names and JSON values.@@ -57,15 +77,20 @@         => v -- ^ bound value         -> Binder (Greskell v) -- ^ variable newBind val = Binder $ do-  (next_index, values) <- State.get-  State.put (succ next_index, values ++ [toJSON val])+  state <- State.get+  let next_index = varIndex state+      values = varBindings state+  State.put $ state { varIndex = succ next_index,+                      varBindings = values ++ [toJSON val]+                    }   return $ unsafePlaceHolder next_index  -- | Execute the given 'Binder' monad to obtain 'Binding'. runBinder :: Binder a -> (a, Binding) runBinder binder = (ret, binding)   where-    (ret, (_, values)) = State.runState (unBinder binder) (0, [])+    (ret, state) = State.runState (unBinder binder) initBinderS+    values = varBindings state     binding = HM.fromList $ zip (map toPlaceHolderVariableStrict [0 ..]) $ values     toPlaceHolderVariableStrict = TL.toStrict . toPlaceHolderVariable @@ -83,4 +108,18 @@ -- -- Create placeholder variable string from the index. toPlaceHolderVariable :: PlaceHolderIndex -> TL.Text-toPlaceHolderVariable i =  TL.pack ("__v" ++ show i)+toPlaceHolderVariable i = TL.pack ("__v" ++ show i)++-- | Create a new 'AsLabel'.+--+-- The returned 'AsLabel' is guaranteed to be unique in the current+-- monadic context.+--+-- @since 0.2.2.0+newAsLabel :: Binder (AsLabel a)+newAsLabel = Binder $ do+  state <- State.get+  let label_index = asLabelIndex state+      label = "__a" ++ show label_index+  State.put $ state { asLabelIndex = succ label_index }+  return $ AsLabel $ T.pack label
src/Data/Greskell/GTraversal.hs view
@@ -95,11 +95,17 @@          gFlatMap,          gV,          gV',+         -- ** As step+         gAs,          -- ** Accessor steps          gValues,          gProperties,          gId,          gLabel,+         gSelect1,+         gSelectN,+         gSelectBy1,+         gSelectByN,          -- ** Summarizing steps          gFold,          gCount,@@ -108,10 +114,14 @@          gOut',          gOutE,          gOutE',+         gOutV,+         gOutV',          gIn,          gIn',          gInE,          gInE',+         gInV,+         gInV',          -- ** Side-effect steps          gSideEffect,          gSideEffect',@@ -153,6 +163,7 @@ import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.Lazy as TL+ import Data.Greskell.Graph   ( Element(..), Vertex, Edge, Property(..),     AVertex, AEdge,@@ -169,6 +180,7 @@     toGremlinLazy, toGremlin   ) import Data.Greskell.AsIterator (AsIterator(IteratorItem))+import Data.Greskell.AsLabel (AsLabel, SelectedMap)  -- $setup --@@ -871,6 +883,15 @@ gV' :: [Greskell GValue] -> Walk Transform s AVertex gV' = gV +-- | @.as@ step.+--+-- @.as@ step is 'Transform' because it adds the label to the+-- traverser.+--+-- @since 0.2.2.0+gAs :: AsLabel a -> Walk Transform a a+gAs l = unsafeWalk "as" [toGremlin l]+ -- | @.values@ step. -- -- >>> toGremlin (source "g" & sV' [] &. gValues ["name", "age"])@@ -902,6 +923,37 @@ gLabel :: Element s => Walk Transform s Text gLabel = unsafeWalk "label" [] +-- | @.select@ step with one argument.+--+-- @since 0.2.2.0+gSelect1 :: AsLabel a -> Walk Transform s a+gSelect1 l = unsafeWalk "select" [toGremlin l]++-- | @.select@ step with more than one arguments.+--+-- @since 0.2.2.0+gSelectN :: AsLabel a -> AsLabel b -> [AsLabel c] -> Walk Transform s (SelectedMap GValue)+gSelectN l1 l2 ls = unsafeWalk "select" ([toGremlin l1, toGremlin l2] ++ map toGremlin ls)++unsafeChangeEnd :: Walk c a b -> Walk c a b'+unsafeChangeEnd (Walk t) = Walk t++byStep :: ByProjection a b -> Walk Transform c c+byStep (ByProjection p) = unsafeWalk "by" [toGremlin p]++-- | @.select@ step with one argument followed by @.by@ step.+--+-- @since 0.2.2.0+gSelectBy1 :: AsLabel a -> ByProjection a b -> Walk Transform s b+gSelectBy1 l bp = modulateWith (unsafeChangeEnd $ gSelect1 l) [byStep bp]++-- | @.select@ step with more than one arguments followed by @.by@+-- step.+--+-- @since 0.2.2.0+gSelectByN :: AsLabel a -> AsLabel a -> [AsLabel a] -> ByProjection a b -> Walk Transform s (SelectedMap b)+gSelectByN l1 l2 ls bp = modulateWith (unsafeChangeEnd $ gSelectN l1 l2 ls) [byStep bp]+ -- | @.fold@ step. gFold :: Walk Transform a [a] gFold = unsafeWalk "fold" []@@ -940,6 +992,18 @@        -> Walk Transform v AEdge gOutE' = gOutE +-- | @.outV@ step.+--+-- @since 0.2.2.0+gOutV :: (Edge e, Vertex v) => Walk Transform e v+gOutV = unsafeWalk "outV" []++-- | Monomorphic version of 'gOutV'.+--+-- @since 0.2.2.0+gOutV' :: Edge e => Walk Transform e AVertex+gOutV' = gOutV+ -- | @.in@ step gIn :: (Vertex v1, Vertex v2)     => [Greskell Text] -- ^ edge labels@@ -963,6 +1027,18 @@       => [Greskell Text] -- ^ edge labels       -> Walk Transform v AEdge gInE' = gInE++-- | @.inV@ step.+--+-- @since 0.2.2.0+gInV :: (Edge e, Vertex v) => Walk Transform e v+gInV = unsafeWalk "inV" []++-- | Monomorphic version of 'gInV'.+--+-- @since 0.2.2.0+gInV' :: Edge e => Walk Transform e AVertex+gInV' = gInV  -- | @.sideEffect@ step that takes a traversal. gSideEffect :: (ToGTraversal g, WalkType c, WalkType p, Split c p) => g c s e -> Walk p s s
test/Data/Greskell/BinderSpec.hs view
@@ -7,8 +7,9 @@ import Data.Text (unpack) import Test.Hspec +import Data.Greskell.AsLabel (AsLabel) import Data.Greskell.Greskell (toGremlin, unsafeGreskell, Greskell)-import Data.Greskell.Binder (newBind, runBinder)+import Data.Greskell.Binder (Binder, newBind, runBinder, newAsLabel)  main :: IO () main = hspec spec@@ -24,7 +25,6 @@     variableHeads = '_' : (['a' .. 'z'] ++ ['A' .. 'Z'])     variableRests = variableHeads ++ ['0' .. '9'] - spec :: Spec spec = describe "Binder" $ do   it "should keep bound values" $ do@@ -48,3 +48,13 @@     got_bind `shouldBe` HM.fromList [ (toGremlin got_v1, toJSON "foobar"),                                       (toGremlin got_v2, toJSON "foobar")                                     ]+  it "should also be able to produce AsLabels" $ do+    let newIntLabel :: Binder (AsLabel Int)+        newIntLabel = newAsLabel+        newVar = newBind "foobar"+        ((got_v1, got_l1, got_v2, got_l2), _) =+          runBinder $ ((,,,) <$> newVar <*> newIntLabel <*> newVar <*> newIntLabel)+    shouldBeVariable got_v1+    shouldBeVariable got_v2+    toGremlin got_v1 `shouldNotBe` toGremlin got_v2+    got_l1 `shouldNotBe` got_l2
test/ServerTest.hs view
@@ -14,6 +14,8 @@ import qualified Network.Greskell.WebSocket.Client as WS import Test.Hspec +import Data.Greskell.AsLabel (AsLabel(..), lookupAsM)+import qualified Data.Greskell.AsLabel as As import Data.Greskell.AsIterator   ( AsIterator(IteratorItem)   )@@ -30,7 +32,7 @@   ) import Data.Greskell.Graph   ( AVertex(..), AEdge(..), AProperty(..), AVertexProperty(..),-    PropertyMapSingle,+    PropertyMapSingle, Key,     T, tId, tLabel, tKey, tValue, cList, (=:),     fromProperties, allProperties   )@@ -41,9 +43,11 @@ import Data.Greskell.GTraversal   ( Walk, GTraversal, SideEffect,     source, sV', sE', gV', sAddV', gAddE', gTo,-    ($.), gOrder, gBy1,+    ($.), gOrder, gBy1, gBy,     Transform, unsafeWalk, unsafeGTraversal,-    gProperties, gProperty, gPropertyV, liftWalk+    gProperties, gProperty, gPropertyV, liftWalk,+    gAs, gSelect1, gSelectN, gSelectBy1, gSelectByN,+    gFilter, gOut'   )  import ServerTest.Common (withEnv, withClient)@@ -59,6 +63,8 @@   spec_T   spec_P   spec_graph+  spec_as+  spec_selectBy   spec_basics :: SpecWith (String,Int)@@ -320,3 +326,52 @@       [ finalize $ gPropertyV (Just cList) "version" ver ["date" =: date] $. liftWalk $ sV' [num vid] $ source "g"       ] ++spec_as :: SpecWith (String,Int)+spec_as = do+  let start :: GTraversal Transform () Int+      start = unsafeGTraversal "__(1,2,3)"+      mult :: Greskell Int -> Walk Transform Int Int+      mult factor = unsafeWalk "map" ["{ it.get() * " <> toGremlin factor <> " }"]+  specify "gAs and gSelect1" $ withClient $ \client -> do+    let label :: AsLabel Int+        label = AsLabel "a"+    got <- WS.slurpResults =<< WS.submit client (gSelect1 label $. mult 100 $. gAs label  $. start) Nothing+    V.toList got `shouldBe` [1,2,3]+  specify "gAs and gSelectN" $ withClient $ \client -> do+    let lorig, lmul :: AsLabel Int+        lorig = AsLabel "a"+        lmul = AsLabel "b"+        gt = gSelectN lorig lmul [] $. mult 5 $. gAs lmul $. mult 100 $. gAs lorig $. start+    got <- fmap V.toList $ WS.slurpResults =<< WS.submit client gt Nothing+    mapM (lookupAsM lorig) got `shouldReturn` [1,2,3]+    mapM (lookupAsM lmul) got `shouldReturn` [100,200,300]++spec_selectBy :: SpecWith (String,Int)+spec_selectBy = do+  let prelude :: Greskell ()+      prelude = unsafeGreskell $ mconcat $ map (<> "; ")+                [ "graph = org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph.open()",+                  "g = graph.traversal()",+                  "graph.addVertex(id, 1, label, 'person')",+                  "graph.addVertex(id, 2, label, 'person')",+                  "g.V(1).property('name', 'ito').property('age', 23).iterate()",+                  "g.V(2).property('name', 'tanaka').property('age', 18).iterate()",+                  "g.V(1).addE('knows').to(V(2)).iterate()"+                ]+  specify "gAs and gSelectBy1" $ withClient $ \client -> do+    let src :: AsLabel AVertex+        src = AsLabel "s"+        gt = gSelectBy1 src (gBy ("name" :: Key AVertex Text)) $. gAs src $. gFilter (gOut' ["knows"]) $. sV' [] $ source "g"+    got <- fmap V.toList $ WS.slurpResults =<< WS.submit client (withPrelude prelude gt) Nothing+    got `shouldBe` ["ito"]+  specify "gAs and gSelectByN" $ withClient $ \client -> do+    let src, dest :: AsLabel AVertex+        src = AsLabel "s"+        dest = AsLabel "d"+        gt = gSelectByN src dest [] (gBy ("age" :: Key AVertex Int))+             $. gAs dest $. gOut' ["knows"]+             $. gAs src $. gFilter (gOut' ["knows"]) $. sV' [] $ source "g"+    got <- fmap V.toList $ WS.slurpResults =<< WS.submit client (withPrelude prelude gt) Nothing+    map (As.lookup src) got `shouldBe` [Just 23]+    map (As.lookup dest) got `shouldBe` [Just 18]