Skip to content

Conversation

@turion
Copy link
Collaborator

@turion turion commented Jul 5, 2021

This implementation of ExceptT has an Applicative instance
that does not need a Monad constraint of the underlying context.

@turion turion force-pushed the dev_selective_except_t branch from f3d1789 to 08b3164 Compare July 5, 2021 11:08
@turion
Copy link
Collaborator Author

turion commented Jul 5, 2021

Do you want to have MaybeT treated in the same way? It would make sense, I guess.

@snowleopard
Copy link
Owner

Do you want to have MaybeT treated in the same way? It would make sense, I guess.

That sounds good but it may be best to finish the ExceptT story first.

Please ping me when this PR is good to review!

@turion
Copy link
Collaborator Author

turion commented Jul 6, 2021

Do you want to have MaybeT treated in the same way? It would make sense, I guess.

That sounds good but it may be best to finish the ExceptT story first.

Yes, agree. I wanted to upload this first stub so you can see the direction we're heading.

@snowleopard
Copy link
Owner

Do you want to have MaybeT treated in the same way? It would make sense, I guess.

That sounds good but it may be best to finish the ExceptT story first.

Yes, agree. I wanted to upload this first stub so you can see the direction we're heading.

My expectation is that MaybeT will be just like ExceptT with e = (), but sure feel free to share the first stub if you like!

@turion
Copy link
Collaborator Author

turion commented Jul 6, 2021

Do you want to have MaybeT treated in the same way? It would make sense, I guess.

That sounds good but it may be best to finish the ExceptT story first.

Yes, agree. I wanted to upload this first stub so you can see the direction we're heading.

My expectation is that MaybeT will be just like ExceptT with e = (), but sure feel free to share the first stub if you like!

Oh yes, I believe that as well. I rather meant that I wanted to share this PR here with this one file before I go on working everything out, since it contains the essential motivation for doing all that work.

@snowleopard
Copy link
Owner

Sure, sounds good!

@turion turion force-pushed the dev_selective_except_t branch 2 times, most recently from 1d0cb53 to d2e2dc3 Compare July 6, 2021 19:54
@turion turion marked this pull request as ready for review April 28, 2022 10:46
@turion
Copy link
Collaborator Author

turion commented Apr 28, 2022

I don't know why I didn't mark it as ready for review. I believe it is.

@turion turion force-pushed the dev_selective_except_t branch 4 times, most recently from 00b9d3d to 66be5e5 Compare May 2, 2022 09:05
@turion
Copy link
Collaborator Author

turion commented May 2, 2022

Ah, deriving MonadFail of course doesn't work for older GHCs. What's your policy for these situations? Deprecate older GHCs? Don't derive MonadFail? CPP?

@snowleopard
Copy link
Owner

Ah, deriving MonadFail of course doesn't work for older GHCs. What's your policy for these situations? Deprecate older GHCs? Don't derive MonadFail? CPP?

If it's just about MonadFail, then let's just write the instance by hand.

@snowleopard
Copy link
Owner

snowleopard commented May 13, 2022

Could you test this transformer somehow? We do have a little testsuite for checking all Selective laws of various instances.

@turion
Copy link
Collaborator Author

turion commented May 16, 2022

Could you test this transformer somehow? We do have a little testsuite for checking all Selective laws of various instances.

Yes, I'd replicate the Writer test suite and adapt it.

But there is a problem: Where to put the Arbitrary instance for ExceptT? Putting it in the tests is an orphan instance. Also we would probably like to make the instance public so others can use it in their tests as well. But we don't want QuickCheck as a dependency to the main library.

I know two typical solutions to this situation:

  • Orphan instance in tests
  • Declare a cabal flag arbitrary-instance that conditionally activates the QuickCheck dependency. This flag is default false and can be set true for packages that want to test ExceptT (such as the test suite)

I like the second option more.

@turion
Copy link
Collaborator Author

turion commented May 16, 2022

Ah, we have to add an orphan instance for transformers' ExceptT anyways.

@turion turion force-pushed the dev_selective_except_t branch from 66be5e5 to dc4c40d Compare May 16, 2022 09:46
@turion
Copy link
Collaborator Author

turion commented May 16, 2022

I went for the first option for the time being. Are there any extra laws that make sense checking for ExceptT?

@turion
Copy link
Collaborator Author

turion commented May 16, 2022

It becomes more cumbersome to derive instances:

  • MonadFail wasn't re-exported from Control.Monad in older GHCs, that's why older pipelines fail. If I explicitly import it, I get an unused-import warning on newer GHCs.
  • Data.Functor.Contravariant doesn't exist in GHC < 8.6 (or rather the corresponding base).

Again the question what to do. Some options:

  1. Drop older GHCs
  2. CPP
  3. Don't add instances for MonadFail and Contravariant

I personally like 1. by far the most. But of course the choice is yours.

@snowleopard
Copy link
Owner

snowleopard commented Jun 14, 2022

@turion Apologies for the long silence! I somehow missed the notifications.

While I don't mind dropping compatibility with older GHCs in principle, doing this just to support MonadFail and Contravariant instances doesn't seem great. Let's just omit these instances for now. I doubt anyone will notice, to be honest :)

@snowleopard
Copy link
Owner

Are there any extra laws that make sense checking for ExceptT?

I'm not aware of any.

@snowleopard snowleopard changed the title WIP Add custom ExceptT (#37) Add custom ExceptT (#37) Jun 14, 2022
@snowleopard
Copy link
Owner

Orphan instance in tests

Yes, this is fine. Thanks!

This implementation of ExceptT has an Applicative instance
that does not need a Monad constraint of the underlying context.
@turion turion force-pushed the dev_selective_except_t branch from 04519e1 to bbf7313 Compare June 15, 2022 07:26
@turion
Copy link
Collaborator Author

turion commented Jun 15, 2022

Ok, then I think I've done everything :)

@turion
Copy link
Collaborator Author

turion commented Jun 15, 2022

The build failure is caused because except used to have the type Either e a -> Except e a which changed to Either e a -> ExceptT e m a at some point. Older GHC versions somehow require older transformers versions indirectly. Again I'm not sure how to proceed. We can do CPP to have two definitions depending on GHC versions, drop Control.Selective.Trans.Except.except, or drop older GHCs.

@snowleopard
Copy link
Owner

The build failure is caused because except used to have the type Either e a -> Except e a which changed to Either e a -> ExceptT e m a at some point.

Ah, that's unfortunate. Let's use CPP to match the type for older GHC versions.

@turion turion force-pushed the dev_selective_except_t branch from 34109d7 to 5211adb Compare June 15, 2022 13:02
@turion
Copy link
Collaborator Author

turion commented Jun 15, 2022

If we already have CPP, shall I re-add MonadFail and Data.Functor.Contravariant?

@snowleopard
Copy link
Owner

If we already have CPP, shall I re-add MonadFail and Data.Functor.Contravariant?

Sure, let's do that. Thanks!

@turion turion force-pushed the dev_selective_except_t branch from 1dd68d1 to fd33e89 Compare June 15, 2022 14:07
@snowleopard
Copy link
Owner

If we already have CPP, shall I re-add MonadFail and Data.Functor.Contravariant?

Sure, let's do that. Thanks!

Looks like it may be harder than it seemed. Feel free to skip this bit if you like!

@turion
Copy link
Collaborator Author

turion commented Jun 17, 2022

@snowleopard I could figure it out in the end. Ok like this? Then I'll squash.

@snowleopard snowleopard merged commit b883cb4 into snowleopard:master Jun 17, 2022
@snowleopard
Copy link
Owner

Awesome, many thanks! I've squashed the commits.

I think it's a pretty cool new module :) I'll try to release a new version of the library soon.

@turion turion deleted the dev_selective_except_t branch June 19, 2022 15:16
@turion
Copy link
Collaborator Author

turion commented Jun 19, 2022

Awesome, this was great fun :)

turion added a commit to turion/selective that referenced this pull request Jun 19, 2022
@turion
Copy link
Collaborator Author

turion commented Jun 23, 2022

I just realised (again?) that the ExceptT instance is just the one from composing with a Traversable #12 (comment) I believe. So in the long run I think we should define another newtype plus instance for the general case and derive Selective that way.

@turion
Copy link
Collaborator Author

turion commented Jun 23, 2022

Also, was it really necessary to delete the old transformers instance? It's more restrictive than this one, but still it doesn't do any harm, right?

@turion turion mentioned this pull request Jun 23, 2022
@snowleopard
Copy link
Owner

Agreed with both points! It would be cleaner to reuse a general Traversable based implementation in the ExceptT instance. And the old instance can remain, perhaps with a comment pointing to the existence of a less restrictive instance.

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.

2 participants