From 032e26cf9ed236889637e02e56aef7c22721cd23 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 17 Oct 2020 09:27:40 +0530 Subject: prefer applicative over monadic style --- bin/Main.hs | 13 +++++-------- shell.nix | 1 + src/Environment.hs | 7 ++++--- src/Evaluator.hs | 14 +++++++------- src/Parser.hs | 1 - 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/bin/Main.hs b/bin/Main.hs index c66d328..18e1c53 100644 --- a/bin/Main.hs +++ b/bin/Main.hs @@ -20,7 +20,7 @@ readExpr inp = evalExpr :: Env -> String -> IO (LispResult String) evalExpr env inp = runExceptT $ fmap show $ - (liftLispResult $ readExpr inp) >>= eval env + liftLispResult (readExpr inp) >>= eval env repl :: Env -> IO () repl env = do @@ -29,20 +29,17 @@ repl env = do case inp of Nothing -> return () Just ",q" -> return () - Just i -> do - out <- evalExpr env i - either (putStrLn . pp i) putStrLn out - repl env + Just i -> evalExpr env i >>= either (putStrLn . pp i) putStrLn >> repl env main :: IO () main = do args <- getArgs - initEnv <- newEnv + env <- newEnv if null args then do putStrLn ";;; Entering lisk repl ..." - repl initEnv + repl env else do let pp = showError defaults "(lisk-repl)" - evalExpr initEnv (head args) >>= (either (putStrLn . pp) print) + evalExpr env (head args) >>= either (putStrLn . pp) print diff --git a/shell.nix b/shell.nix index 15334f5..0f07252 100644 --- a/shell.nix +++ b/shell.nix @@ -33,6 +33,7 @@ let pkgs.cabal2nix haskellPackages.cabal-install haskellPackages.hoogle + haskellPackages.hlint ]; in pkgs.stdenv.mkDerivation { diff --git a/src/Environment.hs b/src/Environment.hs index 7b3f365..4c444b6 100644 --- a/src/Environment.hs +++ b/src/Environment.hs @@ -8,7 +8,8 @@ module Environment ( Env , IOResult ) where -import Control.Monad (liftM, mapM) +import Control.Applicative ((<$>)) +import Control.Monad (mapM) import Control.Monad.Except import Data.IORef import Data.Maybe (isJust) @@ -44,7 +45,7 @@ setVar :: Env -> String -> Expr -> IOResult () setVar env var val = do ptr <- liftIO $ readIORef env maybe (throwError $ UnboundVariable var) - (liftIO . (flip writeIORef val)) + (liftIO . flip writeIORef val) $ lookup var ptr defineVar :: Env -> String -> Expr -> IOResult () @@ -65,5 +66,5 @@ makeBind (var, val) = do manyBindings :: Env -> [(String, Expr)] -> IO Env manyBindings env binds = do ptr <- readIORef env - extendedEnv <- liftM (++ ptr) $ mapM makeBind binds + extendedEnv <- (++ ptr) <$> mapM makeBind binds newIORef extendedEnv diff --git a/src/Evaluator.hs b/src/Evaluator.hs index 1cc9edd..3d3be02 100644 --- a/src/Evaluator.hs +++ b/src/Evaluator.hs @@ -19,9 +19,9 @@ apply fn args = maybe evalUnquote :: Env -> Expr -> IOResult Expr evalUnquote env (List [Id "unquote", vs]) = eval env vs evalUnquote env (List [Id "quote", vs]) = - liftM (List . ([Id "quote"] ++ ) . (: [])) (evalUnquote env vs) -evalUnquote env (List vs) = liftM List $ mapM (evalUnquote env) vs -evalUnquote env (Vector vs) = liftM Vector $ mapM (evalUnquote env) vs + fmap (List . ([Id "quote"] ++ ) . (: [])) (evalUnquote env vs) +evalUnquote env (List vs) = List <$> mapM (evalUnquote env) vs +evalUnquote env (Vector vs) = Vector <$> mapM (evalUnquote env) vs evalUnquote env literal = return literal evalQuasiQuote :: Env -> Expr -> IOResult Expr @@ -35,12 +35,12 @@ eval _ v@(IntLiteral i) = return v eval _ v@(BoolLiteral b) = return v eval env (Id l) = getVar env l eval _ v@(FloatLiteral f) = return v -eval env v@(Vector xs) = liftM Vector $ mapM (eval env) xs +eval env v@(Vector xs) = Vector <$> mapM (eval env) xs eval env (List[Id "quote", val]) = return val eval env (List[Id "quasiquote", val]) = evalQuasiQuote env val -eval env v@(List[Id "unquote", val]) = throwError $ BadForm "Cannot use `unquote` form outside quasiquote context" v -eval env (List [Id "set!", Id var, val]) = eval env val >>= uncurry (*>) . ((setVar env var) &&& pure) -eval env (List [Id "define", Id var, val]) = eval env val >>= uncurry (*>) . ((defineVar env var) &&& pure) +eval env v@(List[Id "unquote", val]) = throwError $ BadForm "Cannot use `unquote` outside quasiquote form" v +eval env (List [Id "set!", Id var, val]) = eval env val >>= uncurry (*>) . (setVar env var &&& pure) +eval env (List [Id "define", Id var, val]) = eval env val >>= uncurry (*>) . (defineVar env var &&& pure) eval env (List (Id fn : args)) = mapM (eval env) args >>= liftLispResult . apply fn eval env NoReturn = throwError $ BadForm "Invalid usage of non-returning expression" NoReturn diff --git a/src/Parser.hs b/src/Parser.hs index a7f5571..6ec4ba0 100644 --- a/src/Parser.hs +++ b/src/Parser.hs @@ -8,7 +8,6 @@ module Parser ( parseLispValue ) where import Control.Applicative ((<$>)) -import Control.Monad (liftM) import Text.ParserCombinators.Parsec -- TODO: use LispNumber (src/Operators.hs) here instead of IntLiteral and FloatLiteral -- cgit v1.2.3