如何将翻译带到IO monad?

时间:2019-01-01 09:53:18

标签: haskell interpreter language-design

我的问题与in this answer

中编写的简单解释器有关

一个人如何为this interpreter第一个非Monadic 版本)添加IO功能?我的意思是简单地添加一条使用putStrLn的语句。我还不太熟悉Haskell,但是我猜您可以通过某种方式组合IO monad。有人可以指出我正确的方向吗?

CNAME

2 个答案:

答案 0 :(得分:2)

您可以使您的解释器在IO monad中得到结果:

<html>
<head>
    <title>First React App</title>
    <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script  src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>  
</head>
<body>
    <div id="app">

    </div>
    <script type="text/babel">
        const name = 'John doe'
        const handle = '@john_doe'

        function NameComponent (props){
            return <h1>{props.name}</h1>;//The problem is here using JSX syntax
        }

        function HandleComponent(props){
            return <h3>{props.handle}</h3>;
        }

        function App(){
            return (
                <div id="container">
                    <NameComponent name={name}/>
                    <HandleComponent handle={handle}/>
                </div>
            );
        }


        ReactDOM.render(<App />,document.getElementById('app'));
    </script>
</body>
</html>

现在exec :: Stmt -> Store -> IO Store 函数可以在IO中执行任何操作。现有操作将需要进行相应的修改。

答案 1 :(得分:1)

我已经用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)]