module Grakn.Property
( Property(..)
, RolePlayer
, Var
, Name
, VarOrName
, Value(..)
, var
, name
, (.:)
, rp
) where
import Control.Applicative (empty)
import Data.Aeson (FromJSON, FromJSONKey,
FromJSONKeyFunction (FromJSONKeyText),
parseJSON)
import qualified Data.Aeson as Aeson
import Data.Scientific (Scientific)
import Data.Text (Text, unpack)
import Grakn.Util (Convert (convert), commas, with)
import Text.Regex.Posix ((=~))
data Property
= Isa VarOrName
| NameProperty Name
| Rel [RolePlayer]
| Has Name
(Either Value Var)
newtype Var =
Var Text
deriving (Eq, Ord)
newtype Name =
Name Text
deriving (Eq)
data VarOrName
= VarName Var
| TypeName Name
data Value
= ValueString Text
| ValueNumber Scientific
| ValueBool Bool
deriving (Eq)
data RolePlayer =
RolePlayer (Maybe VarOrName)
Var
var :: Text -> Var
var = Var
name :: Text -> Name
name = Name
(.:) :: Convert a VarOrName => a -> Var -> RolePlayer
rt .: player = RolePlayer (Just $ convert rt) player
rp :: Var -> RolePlayer
rp = RolePlayer Nothing
nameRegex :: String
nameRegex = "^[a-zA-Z_][a-zA-Z0-9_-]*$"
instance Show Property where
show (Isa varOrName) = "isa " ++ show varOrName
show (NameProperty n) = "type-name " ++ show n
show (Rel castings) = "(" ++ commas castings ++ ")"
show (Has rt value) = "has " ++ show rt ++ " " ++ showEither value
instance Show RolePlayer where
show (RolePlayer roletype player) = roletype `with` ": " ++ show player
instance Show Value where
show (ValueString text) = show text
show (ValueNumber num) = show num
show (ValueBool bool) = show bool
instance Show Name where
show (Name text)
| str =~ nameRegex = str
| otherwise = show text
where
str = unpack text
instance Show Var where
show (Var v) = '$' : unpack v
instance Show VarOrName where
show (VarName v) = show v
show (TypeName t) = show t
instance Convert Var VarOrName where
convert = VarName
instance Convert Name VarOrName where
convert = TypeName
instance Convert Var RolePlayer where
convert = rp
instance Convert Var (Either Value Var) where
convert = Right
instance Convert Text (Either Value Var) where
convert = Left . ValueString
instance Convert Scientific (Either Value Var) where
convert = Left . ValueNumber
instance Convert Bool (Either Value Var) where
convert = Left . ValueBool
instance FromJSON Value where
parseJSON (Aeson.String s) = return $ ValueString s
parseJSON (Aeson.Number n) = return $ ValueNumber n
parseJSON (Aeson.Bool b) = return $ ValueBool b
parseJSON _ = empty
instance FromJSON Name where
parseJSON (Aeson.String s) = return $ name s
parseJSON _ = empty
instance FromJSON Var where
parseJSON (Aeson.String s) = return $ var s
parseJSON _ = empty
instance FromJSONKey Var where
fromJSONKey = FromJSONKeyText var
showEither :: (Show a, Show b) => Either a b -> String
showEither = either show show