Note that there are some explanatory texts on larger screens.

plurals
  1. POAmbiguous type variables for dependent class constraints
    text
    copied!<p>I'm writing a new authentication system for the <a href="http://snapframework.com/" rel="nofollow">Snap web framework</a>, because the built-in one isn't modular enough, and it has some features that are redundant/"dead weight" for my application. This problem isn't related to Snap at all, though.</p> <p>While doing so, I hit a problem with ambiguous type constraints. In the following code, it seems obvious to me that the type of <code>back</code> can only be the type variable <code>b</code> in the functions type, yet GHC complains that the type is ambiguous.</p> <p>How can I change the following code such that the type of <code>back</code> is <code>b</code>, without using e.g. <code>ScopedTypeVariables</code> (because the problem is with the constraint, not with having too general types)? Is there a functional dependency that is needed somewhere?</p> <p>Relevant type classes:</p> <pre><code>data AuthSnaplet b u = AuthSnaplet { _backend :: b , _activeUser :: Maybe u } -- data-lens-template:Data.Lens.Template.makeLens -- data-lens:Data.Lens.Common.Lens -- generates: backend :: Lens (AuthSnaplet b u) b makeLens ''AuthSnaplet -- Some encrypted password newtype Password = Password { passwordData :: ByteString } -- data-default:Data.Default.Default class Default u =&gt; AuthUser u where userLogin :: Lens u Text userPassword :: Lens u Password class AuthUser u =&gt; AuthBackend b u where save :: MonadIO m =&gt; b -&gt; u -&gt; m u lookupByLogin :: MonadIO m =&gt; b -&gt; Text -&gt; m (Maybe u) destroy :: MonadIO m =&gt; b -&gt; u -&gt; m () -- snap:Snap.Snaplet.Snaplet class AuthBackend b u =&gt; HasAuth s b u where authSnaplet :: Lens s (Snaplet (AuthSnaplet b u)) </code></pre> <p>The code that fails:</p> <pre><code>-- snap:Snap.Snaplet.with :: Lens v (Snaplet v') -&gt; m b v' a -&gt; m b v a -- data-lens-fd:Data.Lens.access :: MonadState a m =&gt; Lens a b -&gt; m b loginUser :: HasAuth s b u =&gt; Text -&gt; Text -&gt; Handler a s (Either AuthFailure u) loginUser uname passwd = with authSnaplet $ do back &lt;- access backend maybeUser &lt;- lookupByLogin back uname -- !!! type of back is ambiguous !!! -- ... For simplicity's sake, let's say the function ends like this: return . Right . fromJust $ maybeUser </code></pre> <p>Full error:</p> <pre><code>src/Snap/Snaplet/Authentication.hs:105:31: Ambiguous type variables `b0', `u0' in the constraint: (HasAuth s b0 u0) arising from a use of `authSnaplet' Probable fix: add a type signature that fixes these type variable(s) In the first argument of `with', namely `authSnaplet' In the expression: with authSnaplet In the expression: with authSnaplet $ do { back &lt;- access backend; maybeUser &lt;- lookupByLogin back uname; ... } src/Snap/Snaplet/Authentication.hs:107:16: Ambiguous type variable `b0' in the constraint: (AuthBackend b0 u) arising from a use of `lookupByLogin' Probable fix: add a type signature that fixes these type variable(s) In a stmt of a 'do' expression: maybeUser &lt;- lookupByLogin back uname In the second argument of `($)', namely `do { back &lt;- access backend; maybeUser &lt;- lookupByLogin back uname; ... }' In the expression: with authSnaplet $ do { back &lt;- access backend; maybeUser &lt;- lookupByLogin back uname; ... } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload