提问人:Avunz 提问时间:11/5/2023 最后编辑:ChrisAvunz 更新时间:11/7/2023 访问量:66
如何在 haskell 中计算带有 curried 参数的函数?
How to evaluate a function with curried argument in haskell?
问:
我正在编写一个表达式计算器,定义如下:
eval :: LState -> Env -> Lexp -> (LState, Value)
其中 LState 是内存。Env:Variable 和 Value.Lexp 的映射定义如下:
data Lexp = Lid Var | Lfuncall Lexp [Lexp]
(Lexp 还有更多,但其余的对解决我的问题没有用。
值定义如下:
data Value = Vnum Int
| Vbool Bool
| Vref Int
| Vfun ((LState, Value) -> (LState, Value))
使用模式匹配,我编写了函数的第一部分:eval s env (Lfuncall func (arg:args)) =
现在,我尝试使用 foldl 和 lambda 函数,但没有任何效果。
eval s env (Lfuncall func (arg:args)) = let arg' = eval s env arg
args' = map (eval s env) args
in
case eval s env func of
(_, Vfun func') -> foldl func' arg' args'
_ -> error "error"
然而,这是行不通的,因为 func' 需要,但它只是 .Lambdas 在解决这个问题方面无处可去。(LState, Value) -> (LState, Value) -> (LState, Value)
(LState, Value) -> (LState, Value)
关于我应该尝试探索什么的任何提示或想法?
答:
你走在正确的轨道上,左折。让我们仔细考虑一下我们将折叠什么功能。它需要一个应该(但不能保证)是一个函数,以及一个将被计算的参数,并且应该返回一个(如果有更多的参数,它将扮演下一个函数的角色)。所以,乍一看脸红,是类型只是:Value
Lexp
Value
folder :: Value -> Lexp -> Value
-- ^ accumulator (function)
-- ^ argument
-- ^ result (used as next accumulator)
如果我们适用于此:foldl
foldl folder :: Value -> [Lexp] -> Value
它采用初始函数和参数列表。
但这并不能处理状态部分。我们需要将当前状态作为累加器的一部分,而不仅仅是当前函数,并且需要返回最终状态。这些参数没有自己的状态。因此,我们的类型为:
folder :: (LState, Value) -> Lexp -> (LState, Value)
由此产生的折叠将是:
foldl folder :: (LState, Value) -> [Lexp] -> (LState, Value)
获取初始状态、初始函数、参数列表,并给出最终状态和最终结果。这加起来。所以现在我们需要做的就是用这个签名写,我把它作为一个练习。folder
需要记住的一些事情。永远不要丢弃一个状态或两次使用它——这被称为线性,它对于“有状态计算”的想法非常重要。状态计算通常具有这种模式
let (s1, x) = something s0
(s2, y) = something s1
(s3, z) = something s2
in (s3, something)
因此,我们从上一步中获取结果状态并将其传递给下一步,返回最后一步。
为了调用,必须能够访问 。为此,可以在子句中定义:eval
folder
env
folder
where
eval s env (Lfuncall func args) = ...
where
folder :: (LState, Value) -> Lexp -> (LState, Value)
folder (s0, Vfun f) argExp = -- use env freely here
我希望这会有所帮助。我故意对一些细节有点含糊不清,因为你真的只需要用头撞它才能得到模式,如果有什么需要进一步澄清的,请告诉我。
评论