Home > Net >  Non-exhaustive patterns in this function
Non-exhaustive patterns in this function

Time:04-17

I am trying to code runByte which executes a sequence of instructions and, when finished, returns the value at the top of the stack. If there is an error during execution returns Nothing. I have this Data type and function.

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])

It works when I try make a single operation like runBytecode [PUSH 1, PUSH 2, ADD] but when I try multiple operations runBytecode [PUSH 1, PUSH 4, PUSH 9, MULT, ADD] I get Non-exhaustive patterns, how can I change my pattern matching to all these cases?

CodePudding user response:

You list expressions only work on lists with exactly one or three elements. You should work with a stack such that items are pushed on the stack, and then popped and the result is pushed, so:

runBytecode :: [Bytecode] -> Maybe Int
runBytecode = go []
    where go (x:_) [] = Just x
          go xs (PUSH x:ys) = go (x:xs) ys
          go (x1:x2:xs) (ADD:ys) = go (x1 x2:xs) ys
          # ⋮
          go _ _ = Nothing

Here we thus use as pattern (x1:x2:xs) and (ADD:ys): this will match a non-empty list with ADD as first item, but xs is a list with an arbitrary number of remaining elements.

  • Related