首页 > 解决方案 > Haskell - 作为函数的输入

问题描述

我正在为一小步 WHILE 解释器查看此代码,并且我正在尝试了解如何运行它。具体来说,我对 State 类型感到困惑。它似乎是一种函数 - 这是否意味着必须在某处定义 State = Var->Val 类型的函数,并且该函数需要传递给需要它的函数?

同时,我看到状态应该可以通过变量赋值来修改。如果 upd 函数只传递给 Var->Val 类型的函数,它是如何工作的?

谢谢你的帮助!我似乎在教程或 stackoverflow 上找不到任何关于此的内容。

type Var = Integer
type Val = Integer
type State = Var -> Val


--takes a var, returns a val. Here, we use an integer to describe a
-- variable as opposed to a string.
lkp :: Var -> State -> Val
lkp x s = s x

upd :: Var -> Val -> State -> State
upd x v s = \y -> if x == y then v else s y

data AExp = N Integer | V Var
            | AExp :+ AExp | AExp :- AExp | AExp :* AExp
   deriving (Show)

aexp :: AExp -> State -> Integer
aexp (N z) _ = z
aexp (V x) s = lkp x s
aexp (a0 :+ a1) s = aexp a0 s + aexp a1 s
aexp (a0 :- a1) s = aexp a0 s - aexp a1 s
aexp (a0 :* a1) s = aexp a0 s * aexp a1 s

data BExp = TT | FF | AExp :== AExp | AExp :<= AExp
            | Not BExp | BExp :&& BExp | BExp :|| BExp
   deriving (Show)

bexp :: BExp -> State -> Bool
bexp TT _ = True
bexp FF _ = False
bexp (a0 :== a1) s = aexp a0 s == aexp a1 s
bexp (a0 :<= a1) s = aexp a0 s <= aexp a1 s
bexp (Not b) s = not (bexp b s)
bexp (a0 :&& a1) s = bexp a0 s && bexp a1 s
bexp (a0 :|| a1) s = bexp a0 s || bexp a1 s

data Stmt = Skip | Stmt :\ Stmt | Var := AExp
            | If BExp Stmt Stmt | While BExp Stmt

data Trace = Nil State | Delay State Trace

--reduces the statement by one step.
red :: Stmt -> State -> Maybe (Stmt, State)
red Skip s = Nothing
red (x := a) s = Just (Skip, upd x v s) where v = aexp a s
red (stmt0 :\ stmt1) s =
    case red stmt0 s of
        Just (stmt0', s') -> Just (stmt0' :\ stmt1, s')
        Nothing -> red stmt1 s
red (If b stmt0 stmt1) s =
    if bexp b s then
        Just (stmt0, s)
    else Just (stmt1, s)
red (While b stmt0) s =
    if bexp b s then
        Just (stmt0 :\ While b stmt0, s)
    else Just (Skip, s)

norm :: Stmt -> State -> Trace
norm stmt s =
    case red stmt s of
        Nothing -> Nil s
        Just (stmt', s') -> Delay s (norm stmt' s')

标签: haskellfunctional-programming

解决方案


您可以将State类型视为可以查找变量的环境。您可以从一个“空”环境开始,如下所示:

emptyState v = error ("variable " ++ show v ++ " is unknown")

据我所知,每次解释器看到一个

var := value

构造。也就是说,之后

V 23 := 42

后续语句中使用的状态函数将如下所示:

state1 v = if v == 23 then 42 else emptyState v

有趣的是,emptyState函数的设置决定了解释语言的重要语义属性。emptyState例如,上面禁止未定义的变量。但也有可能想出一个变体,将所有未定义的变量视为 0、1 或 42。


推荐阅读