我正在制作一个基于堆栈的伪汇编虚拟机。以下是问题函数中使用的一些自定义类型:
type Program = Array Int Opcode
type Labels = Map String Int
type Stack = [Integer]
type Memory = Map String Integer
type VarList = [(String, Integer)]
这是问题功能;还有大约20个其他案例,但我只想把与这个问题相关的3个案例:
runFrom :: Int -> Program -> VarList -> String
runFrom i p vars = step i [] (fromList vars) [] where
labels = labelMap p
step i stack mem out =
case ((Array.!) p i, stack) of
(CALL name, s) -> step ((Map.!) labels name) ((i+1):s) mem out
(INT n, s) -> step (i+1) (n:s) mem out
(J name, s) -> step ((Map.!) labels name) s mem out
首先,问题是“CALL”案;当“CALL”被注释掉时,另外两个案例工作正常。为了清楚起见,“INT Integer”将一个Integer压入堆栈,“J String”无条件地跳转到映射到String名称的指令。 “CALL String”应该将下一条指令(i + 1)的索引压入堆栈并无条件跳转到标签名称。但是,如果我尝试加载上面的代码,GHC抱怨无法在“INT”情况下的步骤的第二个参数中将预期的Integer类型与推断的Int类型匹配。因为当“CALL”被注释掉时“INT”工作正常,我假设在CALL中发生了一些棘手的问题(也许是((i + 1):s)?)。有人可以帮我修理CALL吗?
答案 0 :(得分:6)
您的Int
和Integer
不一致......如果您有某些特定原因需要在不同情况下使用它们,并且还要从一个转换为另一个,请使用{{1作为显式转换。否则只需坚持一个(可能是fromIntegral
)。
答案 1 :(得分:3)
因为type Labels = Map String Int
所以标签映射到Int
,而Stack
,Memory
和VarList
使用Integers
。 CALL
强制step
的第一个参数为Int
,这与使用INT
和J