Monad Transformers: Implementing a Stack Machine with MaybeT (State Stack)

I am trying to implement a Maybe-State monad transformer and use it to implement a simple stack machine. The definitions of a state monad and may need to be correct. Now I am trying to implement pop:

pop :: MaybeT (State Stack) Int

So, if the stack is empty, it returns nothing, otherwise it returns Just <popped stack>. This is what I still have:

pop :: MaybeT (State Stack) Int
pop = guard True (do (r:rs) <- get
                     put rs
                     return r)

(Obviously True- this is just a fictitious placeholder - I will fulfill the condition later, while I want to get the other part on the right).

What is wrong with my code? In my understanding, it guardtakes conditional ( True) and the function f. If the conditional value is true, it gives pure f.

In my case

pure = MaybeT . return . Just

So, shouldn't my function f just return State Stack Int?


MaybeT State:

import Control.Applicative (Alternative(..))
import Control.Monad (liftM, ap, guard)
import Control.Monad.Trans.Class (MonadTrans(lift))

main :: IO()
main = return ()


-- State Monad
--------------

newtype State s a = MakeState { runState :: s -> (a, s) }

instance Functor (State s) where
    fmap  = liftM


instance Applicative (State s) where
    pure a = MakeState $ \s -> (a, s)
    (<*>)  = ap

instance Monad (State s) where
    return a = MakeState $ \s -> (a, s)
    m >>= k  = MakeState $ \s -> let (x, s') = runState m s
                              in runState (k x) s'

get :: State s s
get = MakeState $ \s -> (s, s)

put :: s -> State s ()
put s = MakeState $ \_ -> ((), s)

modify :: (s -> s) -> State s ()
modify f = MakeState $ \s -> ((), f s)

-- MaybeT MonadTransformer
---------------------------

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) }

instance Monad m => Functor (MaybeT m) where
    fmap a x = MaybeT $ do e <- runMaybeT x
                           return $ fmap a e



instance Monad m => Applicative (MaybeT m) where
    pure      = MaybeT . return . Just
    (<*>) a b = MaybeT $ do e <- runMaybeT a
                            f <- runMaybeT b
                            return $ e <*> f

instance Monad m => Monad (MaybeT m) where
    return  = pure
    a >>= b = MaybeT $ do aa <- runMaybeT a
                          maybe (return Nothing) (runMaybeT . b) aa


instance Monad m => Alternative (MaybeT m) where
  empty   = MaybeT $ return Nothing
  a <|> b = MaybeT $ do aa <- runMaybeT a
                        bb <- runMaybeT b
                        return $ aa <|> bb


instance MonadTrans MaybeT where
    -- "herwrappen" van het argument
    lift x = MaybeT $ do r <- x
                         return $ Just r


-- Stack Manipulation
---------------------

type Stack = [Int]

-- plaats het argument bovenop de stack
push :: Int -> State Stack ()
push x = do r <- get
            put (x:r)
-- geef de grootte van de stack terug
size :: State Stack Int
size = do r <- get
          return $ length r

-- neem het eerste element van de stack, als het aanwezig is
-- (hint: hoogle naar `guard`)
pop :: MaybeT (State Stack) Int
pop = guard (True) (do (r:rs) <- get
                       put rs
                       return r)
+1
3

, , , r:rs <- get . do-block, fail. Monad m => MaybeT m : fail _ = MaybeT (return Nothing). , , Nothing. , .

, :

pop :: MaybeT (State Stack) Int
pop = do r:rs <- get
         put rs
         return r
+2

guard , Bool.

MaybeT:

pop :: MaybeT (State Stack) Int
pop = do
  guard True
  (r:rs) <- lift get
  lift $ put rs
  return r
+2

, , guard, fail:

pop :: MaybeT (State Stack) Int
pop = do
  stk <- lift get
  case stk of
    [] -> empty
    (r:rs) -> do
      lift (put rs)
      return r

The product empty, when the stack []is equal to the one used guardas you intend, or use failfor a failed pattern matching (as in response to freestyle).

+1
source

Source: https://habr.com/ru/post/1680912/


All Articles