Skip to content

[TEST] strictness tests for the Strict|Lazy State monad - #132

Open
ynishiza wants to merge 4 commits into
haskell:mainfrom
ynishiza:test/strictness-state
Open

ynishiza wants to merge 4 commits into
haskell:mainfrom
ynishiza:test/strictness-state

Conversation

@ynishiza

@ynishiza ynishiza commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

Tests for the Lazy|Strict State transformer.

The approach is analogous to the Writer tests in #127.

  • State functions: evalStateT, execStateT, mapStateT, withStateT, put, modify, modify', modifyM gets
  • Functor/Applicative/Monad: fmap, <*>, liftA2, >>= (same as the Writer tests)
  • Other type classes: Contravariant, MonadFix (same as the Writer tests)
  • lifts: writer lifts liftListen, liftPass, since the behavior differs for these, as it did also in the Writer transformers

@ynishiza
ynishiza force-pushed the test/strictness-state branch from 081bda7 to 94ca230 Compare October 11, 2026 10:22
@ynishiza ynishiza changed the title [TEST] strictness tests for the State monad (Lazy/Strict) [TEST] strictness tests for the Strict|Lazy State monad Oct 11, 2026
@ynishiza
ynishiza force-pushed the test/strictness-state branch from 94ca230 to 83eb097 Compare October 11, 2026 10:52
Comment thread test/Arbitrary.hs
Comment on lines 45 to +46
data BaseMonad
= forall m. (Typeable m, Monad m) => LazyBaseMonad (forall a. m a -> IO a)
| forall m. (Typeable m, Monad m) => StrictBaseMonad (forall a. m a -> IO a)
= forall m. (Typeable m, Monad m) => BaseMonad (forall a. m a -> IO a)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I simplified this to just BaseMonad since there are different nuances of strictness which can get complicated to categorize.

Instead, if there is a difference in the behavior depending on the underlying monad, I opted to just check the actual monad type directly and explain with a comment, as done in one of the tests here.
Please let me know if you have any thoughts.

Comment thread test/StrictnessCheck.hs

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just the strictness assertions moved out of the writer tests

Comment thread test/StateStrictness.hs
Comment on lines +204 to +220
-- In general, the computations are lazy since this is the Lazy State.
--
-- However, one exception is modify', which enforces strictness on the state value.
-- Thus, modify' will bottom for monads which are strict in the underlying sequencing.
-- i.e. Solo and IO
--
-- In particular, note that Identity is lazy whereas Solo is strict:
--
-- m >>= k = k (runIdentity m) lazy runIdentity
-- MkSolo x >>= k = k x strict pattern match
--
let expected = (baseMonadName m == "Solo" || baseMonadName m == "IO") && isBottom (f (snd (x 0)))
in shouldBeBottomIO expected $ withBaseMonad m $ flip Lazy.runStateT 0 $ do
p <- Lazy.StateT $ return . x
q <- Lazy.get

Lazy.modify' f -- may throw depending on the underlying monad. See above.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example mentioned above.

@ynishiza
ynishiza force-pushed the test/strictness-state branch from 83eb097 to 1781938 Compare October 11, 2026 10:56
@ynishiza
ynishiza marked this pull request as ready for review October 11, 2026 10:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant