Skip to content
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

Add FreeTrace.hs #10

Closed
wants to merge 12 commits into from
Closed

Add FreeTrace.hs #10

wants to merge 12 commits into from

Conversation

ghost
Copy link

@ghost ghost commented Nov 14, 2014

Following up on the discussion in #9. It compiles but I haven't tested it.

→ EitherT (ErrorTrace t e) m α
runTraceT = run S.empty . _traceT

run ∷ Monad m ⇒ Seq t → ProgramT (TraceF t e m) m α → EitherT (ErrorTrace t e) m α
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use the multi-line style for run (like runTraceT)?

Copy link
Author

Choose a reason for hiding this comment

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

Sure. For go as well or just run since it's top-level?

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmmm, to avoid it looking to gnarly, I'd probably leave go as is; I don't really have a set practice for stuff in where-clauses. Also, would you indent go by two spaces below the where-clause? (Sorry for all the nitpicking!)

Copy link
Author

Choose a reason for hiding this comment

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

Sure, it's fine :)

@jonsterling
Copy link
Contributor

This is very elegant!

@ghost
Copy link
Author

ghost commented Nov 14, 2014

Thanks. Does it seem to work as expected or do you need those instances before trying it?

{-# LANGUAGE UnicodeSyntax #-}

module Control.Monad.Trans.FreeTrace
where
Copy link
Author

Choose a reason for hiding this comment

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

Just a reminder to fix the exports.

@jonsterling
Copy link
Contributor

When I get some time today, I'll try and write a little demo with this version to make sure it does what I expect; it looks right, fwiw.

Scope ∷ t → TraceT t e m α → TraceF t e m α
Throw ∷ e → TraceF t e m α

-- | The Free Trace Monad.
Copy link
Author

Choose a reason for hiding this comment

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

Call it the Free Trace monad transformer and drop the punctuation.

Copy link
Contributor

Choose a reason for hiding this comment

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

Do you have any thoughts on perhaps a less general name than Trace here? Since I would expect the "Free Trace monad (transformer)" to be something like the smallest possible implementation of MonadTrace, but this also has error-handling semantics. I couldn't think of anything, so I called my thing TraceT, but I think it's not optimal.

If you can't think of anything, I'm fine deferring the name-change to a different time.

Copy link
Author

Choose a reason for hiding this comment

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

Hmm, good question. I don't have a suggestion just now. One possibility would be to define free Trace without error-handling along with another free monad just for error handling and then composing their interpreters. This is pretty easy to do with free monads I think (although I haven't tried specifically with operational). That way you'd have "the smallest trace thing" along with "the smallest trace thing with error-handling".

It's also worth mentioning that there is already something called Trace but it's a comonad. I think it's CoWriter. Maybe I should figure out how it works…

Copy link
Author

Choose a reason for hiding this comment

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

I should mention that the only reason I put the error-handling stuff in there was to be able to define the MonadError instance with a single structure. But if you're okay with dropping that requirement, having a more minimal structure (or two) seems like a good idea.

@jonsterling
Copy link
Contributor

I think there's a bug in the current trace semantics on master, let me look into that before continuing work on this.

@ghost
Copy link
Author

ghost commented Nov 14, 2014

I think there's a bug in the current trace semantics on master, let me look into that before continuing work on this.

No problem.

-- showParen (p > 10) $
-- foldr (.) id (intersperse (" ∥ "++) $ (foldr (.) id . intersperse ('.':) . fmap shows . F.toList) <$> _etTrace)
-- . (" ⇑ " ++)
-- . shows _etError
Copy link
Author

Choose a reason for hiding this comment

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

Might want to add a Foldable mt constraint to restore some sort of structured printing like this.

@ghost
Copy link
Author

ghost commented Nov 17, 2014

I'm going to go ahead and close the PR but feel free to ping me if you find a way this can work out.

@ghost ghost closed this Nov 17, 2014
@jonsterling
Copy link
Contributor

OK. I think that the fact that it is so non-trivial to implement monad-control for free/operational monads is a pretty strong indictment against that library. Sadly, it's probably here to stay; if I figure out how to implement it for things like this, that would be pretty useful, since it would be a nice path toward cleaner implementations of abstractions in terms of operational, etc. I'll let you know if I have any ideas...

@ghost
Copy link
Author

ghost commented Nov 17, 2014

No worries. Indeed, I think the monad-control issues (and in a different sense, the semantics issues earlier) illustrate the problems with transformers. Algebraic effects would be a better option but even without them I think consistently using free monads in "data types à la carte" fashion would be superior. Sadly, as in this case, many of the standard libraries are not geared to accomodate that.

If you're looking for some yaks to shave, Conor has an interesting draft: Why walk when you can take the tube?. Capturing state as a kind of zipper for Free plus some additional machinery might be a thing…

This pull request was closed.
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