Haskell - 用作函数

时间:2018-05-02 18:59:43

标签: haskell functional-programming

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

与此同时,我发现状态应该可以通过变量赋值来修改。如果只在类型为Var-> Val的函数中传递upd函数,那么upd函数如何工作?

感谢您的帮助!我似乎无法在教程或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')

1 个答案:

答案 0 :(得分:2)

您可以将State类型视为可以查找变量的环境。你可以从&#34;空&#34;开始像这样的环境:

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的变体。