Я пытаюсь реализовать монадный преобразователь Maybe-State и использовать его для реализации простой стековой машины. Определения монады состояния и, возможно, должны быть правильными. Теперь я пытаюсь реализовать поп:
pop :: MaybeT (State Stack) Int
Так что, если стек пуст, он ничего не возвращает, иначе он возвращает Just <popped stack>
. Это то, что у меня есть до сих пор:
pop :: MaybeT (State Stack) Int
pop = guard True (do (r:rs) <- get
put rs
return r)
(Очевидно, что True
- это просто фиктивный заполнитель - я реализую условие позже, а сейчас я хочу правильно понять другую часть).
Что не так с моим кодом? Насколько я понимаю, guard
принимает условное выражение (True
) и функцию f. Если условное выражение истинно, оно дает pure f
.
В моем случае,
pure = MaybeT . return . Just
Так не должна ли моя функция f просто возвращать 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)
guard
возвращаетMaybeT (State Stack) ()
, а вам требуетсяMaybeT (State Stack) Int
. - person Lee   schedule 05.12.2016