diff options
| -rw-r--r-- | sequence.cabal | 1 | ||||
| -rw-r--r-- | sequence.nix | 6 | ||||
| -rw-r--r-- | src/Main.hs | 1 | ||||
| -rw-r--r-- | src/Sequence/Formula.hs | 46 | ||||
| -rw-r--r-- | src/Sequence/Types.hs | 2 | ||||
| -rw-r--r-- | src/Sequence/Utils.hs | 4 |
6 files changed, 54 insertions, 6 deletions
diff --git a/sequence.cabal b/sequence.cabal index ada1546..c7c58e4 100644 --- a/sequence.cabal +++ b/sequence.cabal | |||
| @@ -34,5 +34,6 @@ executable sequence | |||
| 34 | , table-layout | 34 | , table-layout |
| 35 | , game-probability | 35 | , game-probability |
| 36 | , readline | 36 | , readline |
| 37 | , either | ||
| 37 | hs-source-dirs: src | 38 | hs-source-dirs: src |
| 38 | default-language: Haskell2010 \ No newline at end of file | 39 | default-language: Haskell2010 \ No newline at end of file |
diff --git a/sequence.nix b/sequence.nix index ff36401..a272486 100644 --- a/sequence.nix +++ b/sequence.nix | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | { mkDerivation, base, bimap, case-insensitive, containers | 1 | { mkDerivation, base, bimap, case-insensitive, containers |
| 2 | , data-default, directory, filepath, game-probability, lens, mtl | 2 | , data-default, directory, either, filepath, game-probability, lens |
| 3 | , readline, Shellac, Shellac-haskeline, stdenv, table-layout | 3 | , mtl, readline, Shellac, Shellac-haskeline, stdenv, table-layout |
| 4 | , xdg-basedir | 4 | , xdg-basedir |
| 5 | }: | 5 | }: |
| 6 | mkDerivation { | 6 | mkDerivation { |
| @@ -11,7 +11,7 @@ mkDerivation { | |||
| 11 | isExecutable = true; | 11 | isExecutable = true; |
| 12 | executableHaskellDepends = [ | 12 | executableHaskellDepends = [ |
| 13 | base bimap case-insensitive containers data-default directory | 13 | base bimap case-insensitive containers data-default directory |
| 14 | filepath game-probability lens mtl readline Shellac | 14 | either filepath game-probability lens mtl readline Shellac |
| 15 | Shellac-haskeline table-layout xdg-basedir | 15 | Shellac-haskeline table-layout xdg-basedir |
| 16 | ]; | 16 | ]; |
| 17 | license = stdenv.lib.licenses.mit; | 17 | license = stdenv.lib.licenses.mit; |
diff --git a/src/Main.hs b/src/Main.hs index 96e3fef..8f955bb 100644 --- a/src/Main.hs +++ b/src/Main.hs | |||
| @@ -33,6 +33,7 @@ import Control.Monad.State.Strict | |||
| 33 | 33 | ||
| 34 | import Sequence.Types | 34 | import Sequence.Types |
| 35 | import Sequence.Utils | 35 | import Sequence.Utils |
| 36 | import Sequence.Formula | ||
| 36 | 37 | ||
| 37 | import Text.Layout.Table | 38 | import Text.Layout.Table |
| 38 | 39 | ||
diff --git a/src/Sequence/Formula.hs b/src/Sequence/Formula.hs new file mode 100644 index 0000000..7a6e689 --- /dev/null +++ b/src/Sequence/Formula.hs | |||
| @@ -0,0 +1,46 @@ | |||
| 1 | {-# LANGUAGE RecordWildCards, RankNTypes, TypeSynonymInstances, FlexibleInstances #-} | ||
| 2 | |||
| 3 | module Sequence.Formula | ||
| 4 | ( FormulaM | ||
| 5 | , evalFormula | ||
| 6 | , val | ||
| 7 | ) where | ||
| 8 | |||
| 9 | import Control.Lens | ||
| 10 | |||
| 11 | import Control.Monad.Trans.Either | ||
| 12 | import Control.Monad.Reader | ||
| 13 | import Numeric.Probability.Game.Event | ||
| 14 | |||
| 15 | import Sequence.Utils | ||
| 16 | |||
| 17 | import Text.Read (readMaybe) | ||
| 18 | |||
| 19 | type FormulaM input a = ReaderT input (EitherT (Question input) EventM) a | ||
| 20 | |||
| 21 | data Question input = Question | ||
| 22 | { answer :: Lens' input (Maybe Int) | ||
| 23 | , prompt :: String | ||
| 24 | } | ||
| 25 | |||
| 26 | instance Integral a => Num (FormulaM input a) where | ||
| 27 | (+) x y = (+) <$> x <*> y | ||
| 28 | (-) x y = (-) <$> x <*> y | ||
| 29 | negate = fmap negate | ||
| 30 | abs = fmap abs | ||
| 31 | signum = fmap signum | ||
| 32 | (*) x y = sum <$> (flip replicateM y =<< fromIntegral <$> x) | ||
| 33 | fromInteger = return . fromInteger | ||
| 34 | |||
| 35 | askQuestion :: MonadIO m => input -> (Question input) -> m input | ||
| 36 | askQuestion input q@(Question{..}) = flip (set answer) input <$> askQ prompt (join . fmap readMaybe) | ||
| 37 | |||
| 38 | evalFormula :: MonadIO m => input -> FormulaM input a -> m a | ||
| 39 | evalFormula input formula = do | ||
| 40 | result <- liftIO . enact . runEitherT . (runReaderT ?? input) $ formula | ||
| 41 | case result of | ||
| 42 | Left q -> askQuestion input q >>= flip evalFormula formula | ||
| 43 | Right result -> return result | ||
| 44 | |||
| 45 | val :: Integral a => Lens' input (Maybe Int) -> String -> FormulaM input Int | ||
| 46 | val answer prompt = view answer >>= maybe (lift . left $ Question{..}) return | ||
diff --git a/src/Sequence/Types.hs b/src/Sequence/Types.hs index 8895569..55c9013 100644 --- a/src/Sequence/Types.hs +++ b/src/Sequence/Types.hs | |||
| @@ -52,7 +52,7 @@ faction' = lens (CI.original . fromMaybe unaligned . view faction) (\s a -> s { | |||
| 52 | | otherwise = Just str' | 52 | | otherwise = Just str' |
| 53 | 53 | ||
| 54 | 54 | ||
| 55 | newtype SeqVal = SeqVal { _seqVal :: Integer } | 55 | newtype SeqVal = SeqVal { _seqVal :: Int } |
| 56 | deriving (Show, Ord, Eq, Num, Integral, Enum, Real) | 56 | deriving (Show, Ord, Eq, Num, Integral, Enum, Real) |
| 57 | makeLenses ''SeqVal | 57 | makeLenses ''SeqVal |
| 58 | 58 | ||
diff --git a/src/Sequence/Utils.hs b/src/Sequence/Utils.hs index 32f8239..f0a8849 100644 --- a/src/Sequence/Utils.hs +++ b/src/Sequence/Utils.hs | |||
| @@ -49,7 +49,7 @@ withFocus f = use gFocus >>= \focus -> case focus of | |||
| 49 | Nothing -> shellPutErrLn $ "Currently not focusing any entity" | 49 | Nothing -> shellPutErrLn $ "Currently not focusing any entity" |
| 50 | Just id -> f id | 50 | Just id -> f id |
| 51 | 51 | ||
| 52 | askBool :: String -> Bool -> Sh st Bool | 52 | askBool :: MonadIO m => String -> Bool -> m Bool |
| 53 | askBool prompt initial = askQ prompt $ fromMaybe initial . join . fmap (eval . CI.mk) | 53 | askBool prompt initial = askQ prompt $ fromMaybe initial . join . fmap (eval . CI.mk) |
| 54 | where | 54 | where |
| 55 | eval "yes" = Just True | 55 | eval "yes" = Just True |
| @@ -58,7 +58,7 @@ askBool prompt initial = askQ prompt $ fromMaybe initial . join . fmap (eval . C | |||
| 58 | eval "n" = Just False | 58 | eval "n" = Just False |
| 59 | eval _ = Nothing | 59 | eval _ = Nothing |
| 60 | 60 | ||
| 61 | askQ :: String -> (Maybe String -> a) -> Sh st a | 61 | askQ :: MonadIO m => String -> (Maybe String -> a) -> m a |
| 62 | askQ prompt eval = eval <$> liftIO (readline $ prompt ++ " ") | 62 | askQ prompt eval = eval <$> liftIO (readline $ prompt ++ " ") |
| 63 | 63 | ||
| 64 | unaligned = view faction' def | 64 | unaligned = view faction' def |
