-
Notifications
You must be signed in to change notification settings - Fork 3
Monadic Logging & Evaluation in Haskell #9
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Added some comments and questions
- Suggested changes to MonadEval.hs so it can be loaded in ghci
logDivs f arg@(Div (x,y)) = logDivs f x >>= logSecond | ||
where | ||
logSecond n = logDivs f y >>= combineWith n | ||
combineWith nm den = writer (f $ Div (Cons nm, Cons den),1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's an interesting idea to have logDivs
wrap around the evalSim
, but it looks like this implementation will apply f
every time it recurses, leading to unnecessary evaluations. Was this intended?
-- where the @Identity@ monad comes in handy because it allows to | ||
-- pack the value of @evalSim@ for use with @logDivsU@: | ||
logDivUSim :: Term -> WriterT (Sum Int) Identity Int | ||
logDivUSim = logDivU (Identity . evalSim) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, I see. You wrap it in an Identity
Monad when you want to turn a simple value into a monadic value to be elsewhere
module MonadEval | ||
where | ||
|
||
import Control.Monad.Writer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import Control.Monad.Writer | |
import Control.Monad | |
import Control.Monad.Identity | |
import Control.Monad.Writer | |
import Data.Monoid |
|
||
-- | This can be used with @evalSafe@ | ||
logDivUSafe :: Term -> WriterT (Sum Int) (Either String) Int | ||
logDivUSafe = logDivU evalSafe |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logDivUSafe = logDivU evalSafe | |
logDivUSafe = logDivsU evalSafe |
-- where the @Identity@ monad comes in handy because it allows to | ||
-- pack the value of @evalSim@ for use with @logDivsU@: | ||
logDivUSim :: Term -> WriterT (Sum Int) Identity Int | ||
logDivUSim = logDivU (Identity . evalSim) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logDivUSim = logDivU (Identity . evalSim) | |
logDivUSim = logDivsU (Identity . evalSim) |
Thanks for your comments. I'm terribly busy with taxes at the moment, so
it'll probably take me until sometime next week-end to tackle that.
Cheers,
Matthias
…On Sun, 10 Mar 2019 at 15:39, Vinicius ***@***.***> wrote:
***@***.**** commented on this pull request.
- Added some comments and questions
- Suggested changes to MonadEval.hs so it can be loaded in ghci
------------------------------
In 2019-02-28-Monad-structure/MonadEval.hs
<#9 (comment)>:
> +evalSafe (Cons x) = return x
+
+-- |For logging, the monad to use is @writer w@ because the logging
+-- value of type @w@ is accumulated automatically when chaining through
+-- monadic values. That's why @w@ is required to be an instance of @monoid@,
+-- which allows the accumulation of values with the monoidal composition.
+-- Whilst @State@ could be used as well, the accumulation would have to be
+-- done manually.
+-- For counting divisions, a @writer (Sum Int) Int@ monad is
+-- called for because @sum Int@ is the monoid with @0@ as neutral element
+-- and @+@ as operation.
+logDivs :: (Term -> Int) -> Term -> Writer (Sum Int) Int
+logDivs f arg@(Div (x,y)) = logDivs f x >>= logSecond
+ where
+ logSecond n = logDivs f y >>= combineWith n
+ combineWith nm den = writer (f $ Div (Cons nm, Cons den),1)
It's an interesting idea to have logDivs wrap around the evalSim, but it
looks like this implementation will apply f every time it recurses,
leading to unnecessary evaluations. Was this intended?
------------------------------
In 2019-02-28-Monad-structure/MonadEval.hs
<#9 (comment)>:
> + where
+ logSecond n = logDivsU f y >>= combineWith n
+ combineWith nm den = WriterT (f (Div (Cons nm, Cons den)) >>= packTup)
+ packTup x = return (x,1)
+logDivsU f arg = WriterT $ f arg >>= \x -> return (x,0)
+
+-- | This can be used with @evalsafe@
+logDivUSafe :: Term -> WriterT (Sum Int) (Either String) Int
+logDivUSafe = logDivU evalSafe
+
+-- | But also with @evalSim@, however @logDivUSim=logDivU evalSim@ does not
+-- work because the value returned by @evalSim@ is not monadic. This is
+-- where the @Identity@ monad comes in handy because it allows to
+-- pack the value of @evalSim@ for use with @logDivsU@:
+logDivUSim :: Term -> WriterT (Sum Int) Identity Int
+logDivUSim = logDivU (Identity . evalSim)
ah, I see. You wrap it in an Identity Monad when you want to turn a
simple value into a monadic value to be elsewhere
------------------------------
In 2019-02-28-Monad-structure/MonadEval.hs
<#9 (comment)>:
> @@ -0,0 +1,100 @@
+module MonadEval
+ where
+
+import Control.Monad.Writer
⬇️ Suggested change
-import Control.Monad.Writer
+import Control.Monad
+import Control.Monad.Identity
+import Control.Monad.Writer
+import Data.Monoid
------------------------------
In 2019-02-28-Monad-structure/MonadEval.hs
<#9 (comment)>:
> +-- which in our case would be @m ~ Either ***@***.*** Note how little the
+-- code has to change from @logDivs@ to its universal version @logDivsU@:
+-- All the @writer@ functions have to be replaced by the @WriterT@ constructors
+-- with some minor adjustments to account for the different argument
+-- requirements.
+logDivsU :: Monad m => (Term -> m Int) -> Term -> WriterT (Sum Int) m Int
+logDivsU f arg@(Div (x,y)) = logDivsU f x >>= logSecond
+ where
+ logSecond n = logDivsU f y >>= combineWith n
+ combineWith nm den = WriterT (f (Div (Cons nm, Cons den)) >>= packTup)
+ packTup x = return (x,1)
+logDivsU f arg = WriterT $ f arg >>= \x -> return (x,0)
+
+-- | This can be used with @evalsafe@
+logDivUSafe :: Term -> WriterT (Sum Int) (Either String) Int
+logDivUSafe = logDivU evalSafe
⬇️ Suggested change
-logDivUSafe = logDivU evalSafe
+logDivUSafe = logDivsU evalSafe
------------------------------
In 2019-02-28-Monad-structure/MonadEval.hs
<#9 (comment)>:
> + where
+ logSecond n = logDivsU f y >>= combineWith n
+ combineWith nm den = WriterT (f (Div (Cons nm, Cons den)) >>= packTup)
+ packTup x = return (x,1)
+logDivsU f arg = WriterT $ f arg >>= \x -> return (x,0)
+
+-- | This can be used with @evalsafe@
+logDivUSafe :: Term -> WriterT (Sum Int) (Either String) Int
+logDivUSafe = logDivU evalSafe
+
+-- | But also with @evalSim@, however @logDivUSim=logDivU evalSim@ does not
+-- work because the value returned by @evalSim@ is not monadic. This is
+-- where the @Identity@ monad comes in handy because it allows to
+-- pack the value of @evalSim@ for use with @logDivsU@:
+logDivUSim :: Term -> WriterT (Sum Int) Identity Int
+logDivUSim = logDivU (Identity . evalSim)
⬇️ Suggested change
-logDivUSim = logDivU (Identity . evalSim)
+logDivUSim = logDivsU (Identity . evalSim)
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#9 (review)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AlnP_AX3ivEM9bV-VLj3lYV-VRWmj5bJks5vVVFvgaJpZM4bbYpJ>
.
|
This is the Haskell version of safe evaluation and division counting plus a combination of both using
monad transformers. Mostly untested, but it illustrates the monad manipulations involved.
Also some updates concerning the January meeting, some questions answered in more detail.