symantic-cli-0.0.0.20180410: Language/Symantic/CLI/Sym.hs
{-# LANGUAGE TypeFamilyDependencies #-}
module Language.Symantic.CLI.Sym where
import Data.Bool
import Data.Char (Char)
import Data.Either (Either(..))
import Data.Eq (Eq)
import Data.Function (($), (.), const, id)
import Data.Functor ((<$>))
import Data.Maybe (Maybe(..), catMaybes)
import Data.Ord (Ord(..))
import Data.String (String)
import Text.Show (Show)
-- * @Arg@ types
-- | Types to type the symantics:
-- eg. to segregate options from commands.
data ArgCommand
data ArgOption
data ArgValue
data ArgRule t
-- * Type 'Name'
type Name = String
-- * Class 'Sym_Fun'
class Sym_Fun repr where
(<$$>) :: (a -> b) -> repr e t a -> repr e t b
(<$$) :: a -> repr e t b -> repr e t a
(<$$) = (<$$>) . const
($$>) :: repr e t b -> a -> repr e t a
r $$> a = const a <$$> r
-- * Class 'Sym_App'
class Sym_Fun repr => Sym_App repr where
value :: a -> repr e ArgValue a
(<**>) :: repr e t (a -> b) -> repr e u a -> repr e u b
(**>) :: repr e t a -> repr e u b -> repr e u b
a **> b = id <$$ a <**> b
(<**) :: repr e t a -> repr e u b -> repr e u a
a <** b = const <$$> a <**> b
end :: repr e t ()
-- * Class 'Sym_Alt'
class Sym_Fun repr => Sym_Alt repr where
(<||>) :: repr e t a -> repr e t a -> repr e t a
choice :: [repr e t a] -> repr e t a
optional :: repr e t a -> repr e t (Maybe a)
optional a = option Nothing (Just <$$> a)
option :: a -> repr e t a -> repr e t a
try :: repr e t a -> repr e t a
-- * Class 'Sym_AltApp'
class (Sym_Alt repr, Sym_App repr) => Sym_AltApp repr where
many :: repr e t a -> repr e t [a]
some :: repr e t a -> repr e t [a]
-- default intermany :: (Sym_Alt repr, Sym_App repr) => [repr e t a] -> repr e t [a]
intermany :: [repr e t a] -> repr e t [a]
intermany = many . choice . (try <$>)
-- * Class 'Sym_Interleaved'
class Sym_Interleaved repr where
interleaved :: Perm (repr e t) a -> repr e t a
(<<$>>) :: (a -> b) -> repr e t a -> Perm (repr e t) b
(<<$?>>) :: (a -> b) -> (a, repr e t a) -> Perm (repr e t) b
(<<$*>>) :: ([a] -> b) -> repr e t a -> Perm (repr e t) b
(<<|>>) :: Perm (repr e t) (a -> b) -> repr e t a -> Perm (repr e t) b
(<<|?>>) :: Perm (repr e t) (a -> b) -> (a, repr e t a) -> Perm (repr e t) b
(<<|*>>) :: Perm (repr e t) ([a] -> b) -> repr e t a -> Perm (repr e t) b
(<<$) :: a -> repr e t b -> Perm (repr e t) a
(<<$) = (<<$>>) . const
(<<$?) :: a -> (b, repr e t b) -> Perm (repr e t) a
a <<$? b = const a <<$?>> b
{- NOTE: cannot be done without and instance:
- Functor (P.PermParser s m)
(<<|) :: Functor (Perm (repr e t)) => Perm (repr e t) a -> repr e t b -> Perm (repr e t) a
(<<|?) :: Functor (Perm (repr e t)) => Perm (repr e t) a -> (b, repr e t b) -> Perm (repr e t) a
a <<| b = (const <$> a) <<|>> b
a <<|? b = (const <$> a) <<|?>> b
-}
infixl 4 <$$>
infixl 4 <**>
infixl 3 <||>
infixl 2 <<$>>, <<$?>>, <<$*>>
infixl 1 <<|>>, <<|?>>, <<|*>>
-- ** Type family 'Perm'
type family Perm (repr:: * -> *) = (r :: * -> *) | r -> repr
-- * Class 'Sym_Rule'
class Sym_Rule repr where
rule :: String -> repr e t a -> repr e t a
-- rule _n = id
-- * Class 'Sym_Command'
class Sym_Command repr where
main :: Name -> repr e t a -> repr e ArgCommand a
command :: Name -> repr e t a -> repr e ArgCommand a
-- * Class 'Sym_Option'
class Sym_AltApp repr => Sym_Option repr where
opt :: OptionName -> repr e s a -> repr e ArgOption a
var :: Name -> (String -> Either e a) -> repr e ArgValue a
tag :: String -> repr e ArgValue ()
-- int :: repr e ArgValue Int
long :: Name -> repr e ArgValue a -> repr e ArgOption a
short :: Char -> repr e ArgValue a -> repr e ArgOption a
flag :: OptionName -> (Bool, repr e ArgOption Bool)
endOpt :: repr e ArgOption ()
string :: Name -> repr e ArgValue String
long = opt . OptionNameLong
short = opt . OptionNameShort
flag n = (False,) $ opt n $ value True
endOpt = option () $ opt (OptionNameLong "") $ value ()
string n = var n Right
-- ** Type 'OptionName'
data OptionName
= OptionName Char Name
| OptionNameLong Name
| OptionNameShort Char
deriving (Eq, Show)
instance Ord OptionName where
x`compare`y =
catMaybes [longOf x, shortOf x]
`compare`
catMaybes [longOf y, shortOf y]
where
longOf = \case
OptionName _s l -> Just l
OptionNameLong l -> Just l
OptionNameShort _s -> Nothing
shortOf = \case
OptionName s _l -> Just [s]
OptionNameLong _l -> Nothing
OptionNameShort s -> Just [s]
-- * Class 'Sym_Help'
class Sym_Help d repr where
help :: d -> repr e t a -> repr e t a
-- * Class 'Sym_Exit'
class Sym_Exit repr where
exit :: e -> repr e t ()