У меня есть тип, который представляет состояние игры для моего приложения, для этого вопроса представьте, что это что-то простое, например:
Game { points :: Int }
Я определяю свою игровую логику с помощью монады State.
type GameState a = StateT Game a
addPoints :: Int -> GameState ()
addPoints num = do
Game p <- get
put $ Game (p+num)
Я хочу иметь возможность просто отбросить некоторые входные данные
evenResult num = do
Game p <- get
return $ even (p + num)
addPoints num = do
isEven <- evenResult num
if isEven then return () else do
Game n <- get
put $ Game (n+num)
Мне нужен синтаксис, который выглядит примерно так
addPoints num = do
guard evenResult
...
-- or this
addPoints num = do
guardIsEvenResult
...
Если он попадает в охранник, я хочу, чтобы он оставил состояние в покое и больше ничего не делал в блоке.
Как мне это сделать? Это кажется близким к возможности с MonadPlus, но я не уверен, что смогу использовать mzero, чтобы сказать «вернуть то, что у вас уже есть в вашем состоянии». Спасибо!
StateT
уже являетсяMonadPlus
. Вы пробовали просто использоватьControl.Monad.guard
? - person Lily Ballard   schedule 24.04.2012StateT s m
- это толькоMonadPlus
, еслиm
; экземпляр просто поднимаетmzero
иmplus
на один уровень выше. - person ehird   schedule 24.04.2012when
хочет значениеBool
, а не вычисление, которое даетBool
. Но Рим сгорел не за один день. Если вашtest
живет вm Bool
, вы могли бы написать(test >>=) . flip when $ action
для небольшого недоумения. - person pigworker   schedule 24.04.2012