summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sequence.cabal1
-rw-r--r--sequence.nix6
-rw-r--r--src/Main.hs1
-rw-r--r--src/Sequence/Formula.hs46
-rw-r--r--src/Sequence/Types.hs2
-rw-r--r--src/Sequence/Utils.hs4
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}:
6mkDerivation { 6mkDerivation {
@@ -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
34import Sequence.Types 34import Sequence.Types
35import Sequence.Utils 35import Sequence.Utils
36import Sequence.Formula
36 37
37import Text.Layout.Table 38import 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
3module Sequence.Formula
4 ( FormulaM
5 , evalFormula
6 , val
7 ) where
8
9import Control.Lens
10
11import Control.Monad.Trans.Either
12import Control.Monad.Reader
13import Numeric.Probability.Game.Event
14
15import Sequence.Utils
16
17import Text.Read (readMaybe)
18
19type FormulaM input a = ReaderT input (EitherT (Question input) EventM) a
20
21data Question input = Question
22 { answer :: Lens' input (Maybe Int)
23 , prompt :: String
24 }
25
26instance 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
35askQuestion :: MonadIO m => input -> (Question input) -> m input
36askQuestion input q@(Question{..}) = flip (set answer) input <$> askQ prompt (join . fmap readMaybe)
37
38evalFormula :: MonadIO m => input -> FormulaM input a -> m a
39evalFormula 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
45val :: Integral a => Lens' input (Maybe Int) -> String -> FormulaM input Int
46val 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
55newtype SeqVal = SeqVal { _seqVal :: Integer } 55newtype SeqVal = SeqVal { _seqVal :: Int }
56 deriving (Show, Ord, Eq, Num, Integral, Enum, Real) 56 deriving (Show, Ord, Eq, Num, Integral, Enum, Real)
57makeLenses ''SeqVal 57makeLenses ''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
52askBool :: String -> Bool -> Sh st Bool 52askBool :: MonadIO m => String -> Bool -> m Bool
53askBool prompt initial = askQ prompt $ fromMaybe initial . join . fmap (eval . CI.mk) 53askBool 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
61askQ :: String -> (Maybe String -> a) -> Sh st a 61askQ :: MonadIO m => String -> (Maybe String -> a) -> m a
62askQ prompt eval = eval <$> liftIO (readline $ prompt ++ " ") 62askQ prompt eval = eval <$> liftIO (readline $ prompt ++ " ")
63 63
64unaligned = view faction' def 64unaligned = view faction' def