Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GHC type functions and scoped type variables

Tags:

haskell

Consider the following, which is written in a context with ScopedTypeVariables:

    defaultGetRestView :: forall view master .
                       ( PersistEntity (PersistentView master view)
                       , PersistStore (YesodPersistBackend master (HandlerT master IO))
                       , MonadTrans (YesodPersistBackend master), YesodPersist master
                       , PersistMonadBackend (YesodPersistBackend master (HandlerT master IO))
                         ~ PersistEntityBackend (PersistentView master view)
                       ) => Key (PersistentView master view) -> HandlerT master IO view

    defaultGetRestView key = ((runDB $ get404 key) :: HandlerT master IO (PersistentView master view))
                         >>= (return . (view :: PersistentView master view -> view))

I am having a type error I don't understand. I am explicitly declaring that the 'view' function that I'm calling is the one that applies to (PersistentView master view):

 NB: `PersistentView' is a type function, and may not be injective
  The type variable `master0' is ambiguous
  Possible fix: add a type signature that fixes these type variable(s)
  Expected type: PersistentView master view -> view
    Actual type: PersistentView master0 view -> view
  In the second argument of `(.)', namely
    `(view :: PersistentView master view -> view)'
like image 486
nomen Avatar asked Oct 26 '25 10:10

nomen


1 Answers

The "may not be injective" is the key part of the error. That is, we may have the equality

PersistentView master view ~ PersistentView master0 view

where master differs from master0. Because of this non-injectivity, writing view :: PersistentView master view -> view fixes the type variable used as a return type (view) but it does not fix the master type variable, which remains ambiguous.

The type for the view function looks inherently ambiguous, in that it allows no way to fix the value of the master type variable. Usually, an extra dummy argument is used for this, as in:

view :: master -> PersistentView master view -> view
view _unused persistentView = ...

Then view (undefined::master) pv would let one to choose the type at which to evaluate view.

like image 62
chi Avatar answered Oct 29 '25 08:10

chi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!