Haskell 如何将口译员带到IO monad?

Haskell 如何将口译员带到IO monad?,haskell,interpreter,language-design,Haskell,Interpreter,Language Design,我的问题是关于用英语写的简单翻译 如何将IO功能添加到(第一个非单声道版本)?我的意思是添加一个使用putStrLn的语句。我还不太精通哈斯克尔,但我猜你可以用某种方式组合IO单子。谁能给我指一下正确的方向吗 data Stmt = Var := Exp | While Exp Stmt | Seq [Stmt]

我的问题是关于用英语写的简单翻译

如何将IO功能添加到(第一个非单声道版本)?我的意思是添加一个使用putStrLn的语句。我还不太精通哈斯克尔,但我猜你可以用某种方式组合IO单子。谁能给我指一下正确的方向吗

data Stmt
  = Var := Exp                                   
  | While Exp Stmt                                               
  | Seq [Stmt]      
  | Print Exp       -- a print statement

您可以使解释器在IO monad中产生结果:

exec :: Stmt -> Store -> IO Store

现在,
exec
函数可以在IO中执行任何操作。现有的操作将需要相应地修改。

我用一个Print语句扩展了您的解释器,该语句将表达式打印到控制台。exec和run的签名必须相应延长:

infixl 6 :+:, :-:
infixl 7 :*:, :/:

data Exp
    = C Int        -- constant                                                     
    | V Var        -- variable                                                     
    | Exp :+: Exp  -- addition                                                     
    | Exp :-: Exp  -- subtraction                                                  
    | Exp :*: Exp  -- multiplication                                               
    | Exp :/: Exp  -- division
    deriving (Show)

infix 1 :=

data Stmt
    = Var := Exp      -- assignment                                                
    | While Exp Stmt  -- loop                                                      
    | Seq [Stmt]      -- sequence
    | Print Exp


type Prog = Stmt

type Var = String
type Val = Int
type Store = [(Var, Val)]

eval :: Exp -> Store -> Val
eval (C n) r       = n
eval (V x) r       = case lookup x r of
                    Nothing -> error ("unbound variable `" ++ x ++ "'")
                    Just v  -> v
eval (e1 :+: e2) r = eval e1 r + eval e2 r
eval (e1 :-: e2) r = eval e1 r - eval e2 r
eval (e1 :*: e2) r = eval e1 r * eval e2 r
eval (e1 :/: e2) r = eval e1 r `div` eval e2 r

exec :: Stmt -> Store -> IO Store
exec (x := e) r                    = return $ (x, eval e r) : r
exec (While e s) r | eval e r /= 0 = exec (Seq [s, While e s]) r
                | otherwise     = return r
exec (Seq []) r                    = return r
exec (Seq (s : ss)) r              = do
                                        r' <- exec s r
                                        exec (Seq ss) r'
exec (Print x) r                   = print (eval x r) >> return r

run :: Prog -> Store -> IO Store
run p r = nubBy ((==) `on` fst) <$> (exec p r)

fib :: Prog
fib = Seq
[ "x" := C 0
, "y" := C 1
, While (V "n") $ Seq
    [ "z" := V "x" :+: V "y"
    , "x" := V "y"
    , "y" := V "z"
    , "n" := V "n" :-: C 1
    , Print (V "x")
    ]
]

main = lookup "x" <$> run fib [("n", 25)]    
infixl 6:+:,:-:
infixl 7:*,:/:
数据扩展
=C Int——常数
|V变量
|Exp:+:Exp--加法
|Exp:-:Exp--减法
|Exp:*:Exp—乘法
|Exp:/:Exp--除法
派生(显示)
中缀1:=
数据Stmt
=Var:=Exp--赋值
|而Exp Stmt——循环
|序列[Stmt]——序列
|打印经验
类型Prog=Stmt
类型Var=String
类型Val=Int
类型存储=[(Var,Val)]
eval::Exp->Store->Val
评估(C n)r=n
eval(V x)r=案例查找x r
Nothing->error(“未绑定变量”`++x++“'))
只要v->v
eval(e1:+:e2)r=eval e1 r+eval e2 r
eval(e1:-:e2)r=eval e1 r-eval e2 r
评估(e1:::e2)r=评估e1 r*评估e2 r
eval(e1:/:e2)r=eval e1 r`div`eval e2 r
exec::Stmt->Store->IO Store
exec(x:=e)r=return$(x,eval e r):r
exec(While e s)r | eval e r/=0=exec(Seq[s,While e s])r
|否则=返回r
exec(Seq[])r=返回r
执行官(Seq(s:ss))r=do

r'什么解释器?中的解释器非常感谢提供完整的实现!