'Recursion/Pattern Matching to evaluate a Postfix expression in Haskell

I am taking an introduction functional programming class, and we are tasked to evaluate a postfix expression in Haskell using a stack. We have covered pattern matching, guards, and recursion so far however I am still struggling to understand how to use Haskell to achieve this. The input of the project is a [String] array, for example ["59","14","-"] (simplest case). We are tasked to solve this which would be 59-14= 45 and return it as a string. The method stub we are given is shown below called "evaluate". What I understand so far is that if the element in the array is not an operator, I need to push to a stack, which I created a method for called "push" but that is obviously wrong. If the element is an operator I need to pop two numbers from the stack and perform the operation, then push it back on the stack. I also understand that I need to recursively call the function evaluate to see all the input. My question is how do I use a stack in Haskell to push numbers, then pop them when I see an operator. For some reason it does not make sense to me in a functional approach. I am just looking for some guidance on this simplest case so I can build from there. I am not sure how to exactly push to a stack then recursively call my "evaluate" function with the rest of the array. Also apologize if this is a bad post, this is my first time asking on here. Thanks

-- Your implementation goes here. Feel free to add more functions.
evaluate :: [String] -> String
evaluate []  = "" 
evaluate("-":xs) = "-"        
evaluate(a:xs) = do 
         push a []
        --/would I call evaluate here?


push::[String]->[Int]->String
push (x:xs) [] = [x]
--not sure what to do after this 

I have tried to create a method called push, that pushes a number to the stack, but I am not sure how to actually push the element on a stack, then recursively call my evaluate function. Maybe I am thinking about this the wrong way.



Solution 1:[1]

Your stack is supposed to return a list: the new stack, so you push an item with:

push:: String -> [Int] -> [Int]
push x xs = read x : xs

or shorter:

push:: String -> [Int] -> [Int]
push = (:) . read

as for the evaluate function, you will need to make use of a helper function that you initialize with an empty stack. You then walk through the list and update the accumulator: the stack until you reach the end of the list of strings to then return the peek of the stack:

evaluate :: [String] -> String
evaluate  = go []
    where go (x:_) [] = …
          go (x1:x2:xs) ("-":ys) = …
          -- ⋮
          go xs (y:ys) = go (push y xs) ys

here for the last line we thus push y on the stack xs and recurse with the new stack as first parameter, and the rest of the items of the list as remaining items. The and ? parts still need to be implemented.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Willem Van Onsem