so, am I using either and ExceptT correctly?
import Control.Monad.IO.Class
import Control.Monad.Trans.Except
foo :: [Int] -> IO [Int]
foo count = (either id pure =<<) . runExceptT . for count $ \u ->
if even u
then throwE $ [u] <$ putStrLn (show u <> " is Even!")
else liftIO $ u <$ print u
vs
bar :: [Int] -> IO [Int]
bar count =
let act a k = if even a
then [a] <$ putStrLn (show a <> " is even!")
else const (a :) <$> print a <*> k in
foldr act (pure []) count
Note that the behavior is subtly different, and I’m unsure how to replicate it with ExceptT.
I’d actually prefer:
foldFor :: Foldable t => t a -> b -> (a -> b -> b) -> b
foldFor foldable def function = foldr function def foldable
baz :: [Int] -> IO [Int]
baz count = foldFor count (pure []) $ \u k ->
if even u
then [u] <$ putStrLn (show u <> " is even!")
else const (u:) <$> print u <*> k
The first and the set of second and third examples aren’t equivalent semantically, anyways, but IIRC that’s a limitation of ExceptT (and why Snoyman went after it on FP Complete).
I think you COULD regain it by compositing ExceptT and StateT? But then… well, maybe later, I’m having very aggravating VPS issues.
Ugh, adding StateT to save the state of ExceptT would require MTL. Sheesh.