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

Superclass constraints are ignored in instances #421

Closed
garyb opened this issue May 22, 2014 · 5 comments
Closed

Superclass constraints are ignored in instances #421

garyb opened this issue May 22, 2014 · 5 comments
Assignees
Milestone

Comments

@garyb
Copy link
Member

garyb commented May 22, 2014

-- With this class definition:

class (Monad m) <= MonadError e m where
  throwError :: forall a. e -> m a
  catchError :: forall a. m a -> (e -> m a) -> m a

-- This instance doesn't work:

instance monadErrorMaybeT :: (MonadError e m) => MonadError e (MaybeT m) where
  throwError e = lift (throwError e)
  catchError = liftCatchMaybe catchError

-- You have to add another `Monad m` constraint:

instance monadErrorMaybeT :: (Monad m, MonadError e m) => MonadError e (MaybeT m) where
  throwError e = lift (throwError e)
  catchError = liftCatchMaybe catchError
@garyb garyb added this to the Backlog milestone May 22, 2014
@garyb garyb added bug labels May 22, 2014
@paf31 paf31 modified the milestones: 0.7.0, Backlog Nov 8, 2014
@paf31 paf31 self-assigned this Nov 15, 2014
@paf31
Copy link
Contributor

paf31 commented Nov 19, 2014

I took a look at this, and it's going to need more work, but I at least know what's wrong.

We can find a Monad m instance if we have a MonadError e m instance, but the issue is that Monad m does not determine e.

@garyb
Copy link
Member Author

garyb commented Nov 20, 2014

Isn't that the wrong way around though? It's Monad m that we're "missing" in the case that fails, no e involved... or is that the problem, that it's "Monad m for all e" (if you see what I mean) that we can't represent right now?

@garyb
Copy link
Member Author

garyb commented Nov 20, 2014

I'm not sure that makes it any clearer actually ;)

I thought this would "just" need fixing by doing something like pulling through the superclass constraints and then applying the current substitution to them when constructing the constraint context. I don't know if that makes sense in the PS typechecker (I'm not sure I've ever looked into the typeclass machinery much), but I was doing something like that in the language I was working on previously.

@paf31
Copy link
Contributor

paf31 commented Nov 20, 2014

@garyb To find the instance for Monad m, the only way is to use the instance for MonadError e m which contains Monad m as a superclass. Which means we need an instance for MonadError e? m, but what is e?? Really it doesn't matter. From a unification perspective, it can be a fresh variable. But the type checker doesn't work that way right now, so it looks for MonadError e <skolemized m> and only finds MonadError <skolemized e> <skolemized m>.

@garyb
Copy link
Member Author

garyb commented Nov 20, 2014

Got it 💡

I wasn't actually seeing the right problem, which didn't help! After playing around with some test cases I see where this arises now.

paf31 added a commit that referenced this issue Mar 15, 2015
@paf31 paf31 modified the milestones: 0.7.0, 0.8.0 Apr 18, 2015
@paf31 paf31 closed this as completed in f5d7b7f Aug 23, 2015
paf31 added a commit that referenced this issue Aug 23, 2015
Fix #421, match type instance heads eagerly
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants