I would venture to guess that the root of your problem is in the expression with authSnaplet . That's why:
βx. x β’ :t with authSnaplet with authSnaplet :: AuthUser u => mb (AuthSnaplet b1 u) a -> mbva
Ignore the context, I filled some dummy instances just for uploading files to GHCi. Notice the type variables here - a lot of ambiguity, and at least two that I expect you intend to be the same type. The easiest way to handle this is probably to create a little helper function with a type signature that narrows some things, like this:
withAuthSnaplet :: (AuthUser u) => Handler a (AuthSnaplet bu) (Either AuthFailure u) -> Handler as (Either AuthFailure u) withAuthSnaplet = with authSnaplet
Again, excuse the stupidity, in fact I donβt have Snap, which makes things uncomfortable. Introducing this function and using it instead of with authSnaplet in loginUser allows you to enter code for verification. You may need to adjust the situation a bit to cope with your actual instance limitations.
Edit: If the method described above does not allow you to mute b any way and assuming that the types are really intended as general than what they are written, then b impossible ambiguously and there is no way around it.
Using with authSnaplet completely eliminates b from the actual type, but leaves it polymorphic with the class constraint on it. This is the same ambiguity as an expression like show . read show . read , has instance-specific behavior, but no way to select it.
To avoid this, you have approximately three options:
Store the ambiguous type explicitly, so b is somewhere in the actual loginUser type, and not just in the context. This may not be desirable for other reasons in the context of your application.
Remove polymorphism by applying only with authSnaplet to the corresponding monomorphic values. If the types are known in advance, there is no room for ambiguity. This potentially means giving up any polymorphism in your handlers, but by sorting things out, you can restrict monomorphism to only code that takes care that b .
Make class restrictions unambiguous. If three parameters of type HasAuth in practice are somewhat interdependent, so that for any s and u will be only one valid instance, then the functional dependence on the rest to b will be fully consistent.
source share