I wrote a function that evaluates an expression.
import Data.Sequence as S (Seq(..), fromList)
import Data.Either (partitionEithers)
data HiFun = HiFunList
deriving (Show,Eq, Ord)
data HiValue = HiValueNumber Rational
| HiValueList (Seq HiValue)
| HiValueFunction HiFun
deriving (Show, Eq, Ord)
data HiExpr = HiExprValue HiValue
| HiExprApply HiExpr [HiExpr]
deriving Show
data HiError = HiErrorInvalidArgument
| HiErrorInvalidFunction
| HiErrorArityMismatch
deriving Show
data HiAction =
HiActionRead FilePath
| HiActionWrite FilePath ByteString
| HiActionMkDir FilePath
| HiActionChDir FilePath
| HiActionCwd
data HiPermission =
AllowRead
| AllowWrite
data PermissionException =
PermissionRequired HiPermission
instance Exception PermissionException
newtype HIO a = HIO { runHIO :: Set HiPermission -> IO a }
--eval :: Monad m => HiExpr -> m (Either HiError HiValue)
eval :: HiMonad m => HiExpr -> m (Either HiError HiValue)
eval (HiExprValue a ) = return (Right a)
eval (HiExprApply (HiExprValue (HiValueNumber _) ) _ ) = return (Left HiErrorInvalidFunction)
eval (HiExprApply exp args ) = do
op <- eval exp
case op of
(Right (HiValueFunction HiFunList)) -> do
ll <- return (fmap (\x -> do a <- eval x ; a ) args) -- args :: [HiExpr]
return (toL ll)
toL :: [(Either HiError HiValue)] -> (Either HiError HiValue)
toL xs = let (ls, rs) = partitionEithers xs in
if (length ls == 0)
then (Right (HiValueList (fromList rs) ))
else (Left HiErrorInvalidArgument)
I had to add
class Monad m => HiMonad m where
runAction :: HiAction -> m HiValue
and change
eval :: Monad m => HiExpr -> m (Either HiError HiValue)
to
eval :: HiMonad m => HiExpr -> m (Either HiError HiValue)
And I got error
• Could not deduce (HiMonad (Either HiError))
arising from a use of ‘eval’
from the context: HiMonad m
bound by the type signature for:
eval :: forall (m :: * -> *).
HiMonad m =>
HiExpr -> m (Either HiError HiValue)
at src\HW3\Evaluator.hs:19:1-57
• In a stmt of a 'do' block: a <- eval x
In the expression:
do a <- eval x
a
In the first argument of ‘fmap’, namely
‘(\ x
-> do a <- eval x
a)’
|
28 | ll <- return (fmap (\x -> do a <- eval x ; a ) args)
| ^^^^^^
As I could understand we don't have
instance HiMonad (Either HiError)
I think instance HiMonad (Either HiError) couldn't be written because of Monad m => HiMonad m Extra Text, Extra Text. Extra Text. Extra Text, Extra Text. Extra Text, Extra Text. Extra Text. Extra Text, Extra Text.
CodePudding user response:
I think I figured out what you're trying to do. You want to eval
all of the arguments, within the same monad the outer eval
is in, and then give that result to toL
. To do that, replace this:
return (fmap (\x -> do a <- eval x ; a ) args)
with this:
traverse eval args
CodePudding user response:
Either HiError
is already a monad. You don't need to add an additional Monad m
layer (nor HiMonad m
), just use it as is.
eval :: HiExpr -> Either HiError HiValue
eval (HiExprValue a) = return a
eval (HiExprApply (HiExprValue (HiValueNumber _)) _) = Left HiErrorInvalidFunction
eval (HiExprApply exp args) = do
op <- eval exp
case op of
HiValueFunction HiFunList -> do
argVals <- mapM eval args
-- the next line mimics the existing code, but you probably want to do
-- something to actually apply op to argVals here in your final version
return (HiValueList (fromList argVals))
HiValueFunction _ -> Left HiErrorArityMismatch -- or whatever...
_ -> Left HiErrorInvalidFunction -- or whatever