-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is Writer wrong? #166
Comments
It should be |
I'll look into this. |
Huh. This is very interesting. Yes, from what I can tell, it's not possible to implement But here's the thing: the semantics of Polysemy's Compare: import Polysemy
import Polysemy.Writer
import Polysemy.Error
import Control.Monad.Except
import qualified Control.Monad.Writer.Class as MTL
one :: (String, Either () ())
one = runExceptT $
do
MTL.tell "censoring"
MTL.censor (drop 4) (MTL.tell " not applied" *> throwError ())
`catchError`
(\_ -> pure ())
-- one == ("censoring not applied", Right ())
two :: (String, Either () ())
two =
run
. runWriter
. runError
$ do
tell "censoring"
censor (drop 4) (tell " not applied" *> throw ())
`catch`
(\_ -> pure ())
-- two == ("censoring applied", Right ()) So to sum it up, we can work |
haskell/mtl#5 (comment) suggests a law for |
This is not Whatever the case, we can only have |
Right, I meant
My point was there is also the option that |
Well, if we want |
Another alternative is to have separate effects for |
Does anyone actually use |
Those MTL.pass (("sim", ()) >>= \_ -> ("salabim", ((), id))) == ("simsalabim", ())
combine ("sim", ()) (\_ -> ("salabim", ((), id))) == ("simsimsalabim", ()) |
https://codesearch.aelve.com/haskell/search?query=pass&filter=Control.Monad.Writer&insensitive=off&space=off&precise=off&sources=on only seems to show people defining |
@ocharles what is this sorcery? this thing exists??? it's like the answer to all of my prayers! |
😘 |
To steal some (modified) code from StackOverflow: deleteOn :: (Monoid w) => (a -> Bool) -> Writer w a -> Writer w a
deleteOn p m = pass $ do
a <- m
if p a
then return (a, id)
else return (a, const mempty) It's only that it doesn't seem to crop up... at all? |
That's a reasonable motivation. I'm inclined to go with the principle of least surprise here and just copy mtl's semantics. Any dissent on that front? |
Given how surprising it is and that we can't find any motivation, I'd rather drop it. Edit: though does this mess up with the whole |
Just as an aside, it looks like Futhark is the sole user of this function in the whole world! https://codesearch.aelve.com/haskell/src/hackage/futhark/0.11.2/src/Futhark/CodeGen/Backends/GenericC.hs?query=pass&L=342#snippet.342 |
... Buuuuut it's a use that can be replaced with |
Hell, conditional logging can be achieved through deleteOn :: (Monoid w) => (a -> Bool) -> Writer w a -> Writer w a
deleteOn p m = do
(a, w) <- censor (const mempty) (listen m)
when (p a) (tell w)
return a Perhaps there are some situations where |
Actually, never mind, that kind of implementation is dangerous with current I dunno. I'm on the fence about this. |
Actually, considering the issue with the censor' :: (MTL.MonadWriter s m, MonadError e m)
=> (s -> s)
-> m a
-> m a
censor' f m = do
res <- MTL.censor f $ fmap Right m `catchError` (pure . Left)
case res of
Right res' -> return res'
Left e -> throwError e
three :: (String, Either () ())
three = runExceptT $
do
MTL.tell "censoring"
censor' (drop 4) (MTL.tell " not applied" *> throwError ())
`catchError`
(\_ -> pure ())
-- three == ("censoring applied", Right ()) |
Just to be clear, the semantics of |
I'm going to add a pull request resolving this issue, together with adding |
IIRC @adamConnerSax was saying our Writer instance doesn't line up with MTL. Is this true, and if so, let's fix it.
The text was updated successfully, but these errors were encountered: