此功能中的非详尽模式

Non-exhaustive patterns in this function

我正在尝试编写 runByte 代码,它执行一系列指令,完成后,returns 堆栈顶部的值。如果在执行过程中出现错误returns Nothing。我有这个数据类型和函数。

data Bytecode = PUSH Int
              | ADD
              | SUB
              | MULT
              | DIV
              deriving (Eq, Show)

runBytecode :: [Bytecode] -> Maybe Int
runBytecode [PUSH x] = Just x
runBytecode [PUSH l, PUSH r, ADD] = (+) <$> (runBytecode [PUSH l]) <*> (runBytecode [PUSH r])
runBytecode [PUSH l, PUSH r, SUB] = (-) <$> (runBytecode [PUSH l]) <*> (runBytecode [PUSH r])
runBytecode [PUSH l, PUSH r, DIV] = (div) <$> (runBytecode [PUSH l]) <*> (runBytecode [PUSH r])
runBytecode [PUSH l, PUSH r, MULT] = (*) <$> (runBytecode [PUSH l]) <*> (runBytecode [PUSH r])

当我尝试像 runBytecode [PUSH 1, PUSH 2, ADD] 这样的单个操作时它有效,但是当我尝试多个操作时 runBytecode [PUSH 1, PUSH 4, PUSH 9, MULT, ADD] 我得到非穷举模式,我如何改变我的模式匹配到所有这些情况?

您的列表表达式仅适用于仅包含一个或三个元素的列表。您应该使用堆栈,以便将项目压入堆栈,然后弹出并压入结果,因此:

runBytecode :: [Bytecode] -> Maybe Int
runBytecode = go []
    where go (x:_) [] = Just x
          go xs (PUSH x:ys) = go (x:xs) ys
          go (x<sub>1</sub>:x<sub>2</sub>:xs) (ADD:ys) = go (x<sub>1</sub>+x<sub>2</sub>:xs) ys
          # ⋮
          go _ _ = Nothing

因此我们在这里使用模式 (x<sub>1</sub>:x<sub>2</sub>:xs)(ADD:ys):这将匹配 non-empty 列表,其中 ADD 作为第一项,但 xs 是一个包含任意数量剩余元素的列表。