this is my first time to use Haskell and i have read many many tutorials about it. But when it came to practice, many problems show up. I m trying to make a stack data structure and use it in the Do block. But when i do this. It says cant match type'Stack' with 'IO', i have no idea about this problem. Following is my code:
import Data.Array.IO
main::IO()
main = do
arr <- newArray((0,0),(8,13)) 0 ::IO (IOArray(Int,Int) Int)
list <- getElems arr
print list
push 0 mystack --here is the problem
return()
data Stack a = Stack [a] deriving Show
empty :: Stack a
empty = Stack []
push :: a -> Stack a -> Stack a
push x (Stack xs)= Stack (x:xs)
pop :: Stack a -> (Maybe a, Stack a)
pop (Stack []) = (Nothing, Stack [])
pop (Stack (x:xs)) = (Just x, Stack xs)
mystack = empty
Problem is below(when i put push 0 mystack in the Do block it shows up)
Couldn't match type `Stack' with `IO'
Expected type: IO Integer
Actual type: Stack Integer
In the return type of a call of `push'
In a stmt of a 'do' block: push 0 mystack
The problem here is that main has type IO (), meaning that any statement inside the do block must have type IO a for some type a. Your data type is Stack a, which does not match IO a. You also look like you're wanting some sort of "mutable state" with your stack, but all your functions are pure, meaning they simply return a new value. Values in Haskell are immutable, meaning that they can't be modified after being declared. For most purposes, Haskell doesn't have variables, just named values.
What you probably really want is to use the State monad. You could modify your push and pop functions to work in that monad instead, and then use execState to run the stateful computation:
import Control.Monad.State
data Stack a = Stack [a] deriving (Eq, Show)
push' :: a -> Stack a -> Stack a
push' x (Stack xs) = Stack (x:xs)
push :: a -> State (Stack a) ()
push x = modify (push' x)
pop' :: Stack a -> (Maybe a, Stack a)
pop' (Stack []) = (Nothing, Stack [])
pop' (Stack (x:xs)) = (Just x, Stack xs)
pop :: State (Stack a) (Maybe a)
pop = state pop'
Notice how easy it was to directly use your already written functions to implement this! You even had pop return the Maybe a in the first element of the tuple to go straight into the state function. You can then use this as
main :: IO ()
main = do
let resultStack = flip execState empty $ do
push 1
push 2
push 3
pop -- pop off 3
Just x <- pop -- pop off 2
push $ 2 * x -- push 4
mapM_ push [1..10] -- Pushes 1 through 10 onto the stack in that order
pop -- pop off 10
pop -- pop off 9
pop -- pop off 8
print resultStack
This will print out
Stack [7, 6, 5, 4, 3, 2, 1, 4, 1]
push 0 mystack returns a new stack. You are not getting the return value, and you are writing this line as an "action". "Actions" are things that change the global state of the system, they are marked by functions returning IO. Since push doesn't change the global state, haskell tells you that there's no reason to call it like you do.
What you probably mean is:
let newStack = push 0 mystack
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With