Ответ 1
Согласно законам тождества монады,
return a >>= const b = const b a = b
Таким образом, в частности,
return undefined >>= const b = b
Если операция >>=
была строкой в значении результата, это нарушило бы этот закон, поэтому вы не должны этого делать.
Предположим, что вы это сделаете:
m >>= k = State $ \s ->
case runState m s of
(a, !s') -> runState (k a) s'
Теперь мы сталкиваемся с другим законом идентичности:
m >>= return = m
Например,
return a >>= return = return a
Итак, если return a >>= return
является строгим в состоянии, тогда мы также должны иметь return a
strict в состоянии! Поэтому нам нужно переопределить return
:
return a = State $ \ !s -> (a, s)
Обратите внимание, что вам действительно не нужно ничего делать; если вы хотите, вы можете использовать обычную строгую государственную монаду и писать такие вещи, как
!_ <- get
в тех точках, где вы хотите заставить состояние. Вы даже можете написать действие, чтобы сделать это:
forceState :: Monad m => StateT s m ()
forceState = get >>= \ !_ -> return ()
Изменить
Даже это определение немного странно для меня; Я ожидал бы, что лямбда заставит государство, а не case
. Я не уверен, что если это не произойдет, это приведет к некоторому поломке, но это меня не удивило бы, если бы это произошло.