Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 执行IO操作,但返回其他类型_Haskell_Io - Fatal编程技术网

Haskell 执行IO操作,但返回其他类型

Haskell 执行IO操作,但返回其他类型,haskell,io,Haskell,Io,对于一个项目,我们的任务是编写命令式语言并通过Haskell执行它。解析器(此处省略)和部分求值已完成。现在只剩下编码效果了。操纵一个小机器人 给定以下代码: data Env = Env [Binding] instance Show Env where show (Env (x:xs)) = show x ++ ", " ++ show (Env xs) show (Env []) = "" data Binding = Binding (String,Int) instance

对于一个项目,我们的任务是编写命令式语言并通过Haskell执行它。解析器(此处省略)和部分求值已完成。现在只剩下编码效果了。操纵一个小机器人

给定以下代码:

data Env = Env [Binding]
instance Show Env where
  show (Env (x:xs)) = show x ++ ", " ++ show (Env xs)
  show (Env []) = ""

data Binding = Binding (String,Int)
instance Show Binding where
  show (Binding x) = fst x ++ " : " ++ show (snd x)

lookup' :: String -> Env -> Int
lookup' zoek (Env env) = case elemIndex zoek [fst x | Binding x <- env] of
  Just y ->  y
  Nothing -> error "Not found"


eval :: Stmt -> Env ->  Env
eval (Seq s) env = foldl (flip eval) env s
eval (Assign varName aexpr) env = evalAssign varName aexpr env
eval (If bool stmt1 stmt2) env = evalIf bool stmt1 stmt2 env
eval (While bool stmt) env = undefined
eval (MotorInstruct string aExpr) env = undefined
eval (SensorRead string) env = undefined
eval Skip env = env

evalAExpr :: AExpr -> Env -> Int
evalAExpr (IntConst int) _  = fromInteger int
evalAExpr (Neg a) env = - evalAExpr a env
evalAExpr (ABinary Add a b) env = evalAExpr a env + evalAExpr b env
evalAExpr (ABinary Subtract a b) env = evalAExpr a env - evalAExpr b env
evalAExpr (ABinary Multiply a b) env = evalAExpr a env * evalAExpr b env
evalAExpr (ABinary Divide a b) env = evalAExpr a env `div` evalAExpr b env
evalAExpr (Var x) env = getElementAtEnv env (lookup' x env)
  where
    getElementAtEnv (Env env) index = getSndFromBinding (env !! index)
    getSndFromBinding (Binding (_,t)) = t


evalBExpr :: BExpr -> Env -> Bool
evalBExpr (BoolConst bool) _ = bool
evalBExpr (Not expr) env = not $ evalBExpr expr env
-- Boolean operators
evalBExpr (BBinary And a b) env = evalBExpr a env && evalBExpr b env
evalBExpr (BBinary Or a b) env = evalBExpr a env || evalBExpr b env
-- Relational operators
evalBExpr (RBinary Greater a b) env = evalAExpr a env > evalAExpr b env
evalBExpr (RBinary Less a b) env = evalAExpr a env < evalAExpr b env
evalBExpr (RBinary Equal a b) env = evalAExpr a env == evalAExpr b env


evalIf ::  BExpr -> Stmt -> Stmt -> Env -> Env
evalIf expr s1 s2 env = if evalBExpr expr env
  then
    eval s1 env
  else
    eval s2 env


evalAssign :: String -> AExpr -> Env -> Env
evalAssign term s (Env env)= if term `elem` transform
  then
    Env ( take (lookup' term (Env env)) env ++ [Binding (term, evalAExpr s (Env env))]++ drop (lookup' term (Env env) + 1) env)
  else
    Env (env ++ [Binding (term, evalAExpr s (Env env))])
  where transform = [ fst ele | Binding ele <- env]


zoekMotor :: String -> Int
zoekMotor "left" = 0x9
zoekMotor "right" = 0xa
zoekMotor _ = error "No such motor"


sendToMotor :: String -> Int -> IO()
sendToMotor m s = do
  bot <- openMBot
  sendCommand bot $ setMotor (zoekMotor m) s s
  closeMBot bot

evalMotorInstruct :: String -> AExpr -> Env -> Env
evalMotorInstruct welke waarde env = do
  sendToMotor welke (evalAExpr waarde env)
  return env
data Env=Env[Binding]
实例Show Env where
show(Env(x:xs))=show x++“,”++show(Env-xs)
显示(环境[])=“”
数据绑定=绑定(字符串,Int)
实例显示绑定在哪里
show(Binding x)=fst x++“:”++show(snd x)
查找“::字符串->环境->整数
查找'zoek(Env Env)=案例elemIndex zoek[fst x | Binding x y
无->错误“未找到”
评估::Stmt->Env->Env
评估(顺序)环境=文件夹(翻转评估)环境
eval(分配varName aexpr)env=evalAssign varName aexpr env
eval(如果bool stmt1 stmt2)env=evalIf bool stmt1 stmt2 env
eval(而bool stmt)env=未定义
eval(字符串aExpr)env=未定义
eval(传感器读取字符串)env=未定义
评估跳过环境=环境
evalAExpr::AExpr->Env->Int
evalAExpr(IntConst int)u=从整数int
evalAExpr(负a)env=-evalAExpr a env
evalAExpr(ABinary Add a b)env=evalAExpr a env+evalAExpr b env
evalAExpr(二进制减去AB)env=evalAExpr a env-evalAExpr b env
evalAExpr(二进制乘法a b)env=evalAExpr a env*evalAExpr b env
evalAExpr(二进制除法a b)env=evalAExpr a env`div`evalAExpr b env
evalAExpr(Var x)env=getElementAtEnv env(查找'x env)
哪里
getElementAtEnv(Env Env)index=getSndFromBinding(Env!!index)
getSndFromBinding(Binding(u,t))=t
evalBExpr::BExpr->Env->Bool
evalBExpr(BoolConst bool)\uuu=bool
evalBExpr(非expr)env=非$evalBExpr expr env
--布尔运算符
evalBExpr(BBinary和ab)env=evalBExpr a env&&evalBExpr b env
evalBExpr(BBinary或ab)env=evalBExpr a env | | evalBExpr b env
--关系运算符
evalBExpr(b)环境=evalAExpr a环境>evalAExpr b环境
evalBExpr(RBinary减去a b)env=evalAExpr a envStmt->Stmt->Env->Env
evalIf expr s1 s2 env=如果evalBExpr expr env
然后
评估s1环境
其他的
评估s2环境
evalAssign::String->AExpr->Env->Env
evalAssign term s(Env Env)=如果term`elem`transform
然后
环境(获取(查找术语(Env Env))环境++[绑定(术语,evalAExpr s(Env Env))]++删除(查找术语(Env Env Env)+1)环境)
其他的
Env(Env++[绑定(术语,evalAExpr s(Env Env))]
其中transform=[fst ele | Binding ele Int
zoekMotor“左”=0x9
zoekMotor“右”=0xa
zoekMotor=错误“无此类电机”
sendToMotor::String->Int->IO()
sendToMotor m s=do
机器人AExpr->Env->Env
EvalMotor welke waarde env=do
sendToMotor welke(evalAExpr waarde环境)
返回环境
如何执行求值函数
evalmotordirection
中的函数
sendToMotor
(返回
IO()
),该函数应返回
Env
?对于如何执行我的“action”函数并仅从求值函数中获取
Env
,我有些不知所措

请注意,
evalmotorinstruction
的当前代码不正确。该函数应返回
Env
,但实际返回
IO Env


谢谢

您的AExpr和BExpr类型在您的语言中表示纯计算-它们不仅不执行任何IO,而且也不修改环境。因此,您不必修改它们的eval函数

因此,您只需修改
Stmt
值的求值。类型签名将更改为:

eval :: Stmt -> Env -> IO Env
eval Seq
将如何更改的示例:

eval (Seq []) env     = return env
eval (Seq (s:ss)) env = do env' <- eval s env  -- eval the first statement
                           eval (Seq ss) env'  -- eval the rest
如果您将其签名更改为:

evalMotorInstruct :: String -> AExpr -> Env -> IO Env
剩下的就交给你了


重构时,只需注释掉未编译的代码。然后逐行递增地添加代码,在添加另一行之前对每行代码进行编译。如果需要,请使用
..=undefined
。稍后再回来填写这些代码。

您已经发现了Haskell的一个有趣特性—它的纯度。您不能t执行IO操作并返回未包装在IO中的结果。这是因为Haskell函数不能执行任意副作用;它们必须是纯函数。根据您使用的
do
return
,您可以返回
IO Env
,这似乎就是您在这里寻找的内容。@AlexisKing这意味着我应该转换吗我的所有其他“eval”函数也返回IO Env?和“unwrapping”在任何情况下都可以使用它们?你可能想考虑使用一个免费的monad来避免使用
IO
@AlexisKing,我尝试了更多地修改代码,以获得例如
evalAssign
返回和接受
IO Env
。我没有成功:/。如果可能的话,你能为我的问题提供一些示例/帮助吗?这需要时间为了弄清楚如何保持纯代码的纯净,以及如何将
IO
业务限制在外围,我可能会尝试稍后再写一个答案,但这可能最好留给一位比我更有经验的老师。对此,一个潜在的改进是使用
StateT Env IO
作为monad,这将允许您不要手动传递
Env
,也可以编写
eval(Seq ss)=mapM_uevalss
等。
evalMotorInstruct :: String -> AExpr -> Env -> IO Env