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

Problem with type inference caused by ! defaults #15

Open
Unisay opened this issue Sep 25, 2018 · 2 comments
Open

Problem with type inference caused by ! defaults #15

Unisay opened this issue Sep 25, 2018 · 2 comments

Comments

@Unisay
Copy link

Unisay commented Sep 25, 2018

I have the following function declared in my typeclass:
https://github.com/DSTOQ/haskell-stellar-client/blob/master/src/Control/Monad/Stellar.hs#L26

When calling it in this way:

lastAccountTransaction :: MonadStellar m => AccountId -> m Transaction
lastAccountTransaction accountId = do
  let txs = accountTransactions accountId
          ! #cursor Nothing
          ! #limit Nothing
          ! #order Nothing

all compiles well,
but if only I try to use ! defaults, I get the following error:

      • Could not deduce (MonadStellar m0)
            arising from a use of ‘accountTransactions’
          from the context: MonadStellar m
            bound by the type signature for:
                       lastAccountTransaction :: forall (m :: * -> *).
                                                 MonadStellar m =>
                                                 AccountId -> m Transaction
            at src/Service/Domain/Offer.hs:40:1-70
          The type variable ‘m0’ is ambiguous
          These potential instances exist:
            instance Control.Monad.Rest.MonadRest m =>
                     MonadStellar (StellarT m)
              -- Defined in ‘Control.Monad.Trans.Stellar’
            instance MonadStellar m => MonadStellar (ExceptT e m)
              -- Defined in ‘Control.Monad.Stellar’
            instance MonadStellar m => MonadStellar (StateT s m)
              -- Defined in ‘Control.Monad.Stellar’
            ...plus four instances involving out-of-scope types
            (use -fprint-potential-instances to see them all)
        • In the first argument of ‘(!)’, namely
            ‘accountTransactions accountId’
          In the expression: accountTransactions accountId ! defaults
          In an equation for ‘txs’:
              txs = accountTransactions accountId ! defaults
@int-index
Copy link
Contributor

The problem is that the type of accountTransactions is polymorphic in its return type:

m ([TransactionDetails], Cursor)

This means that one of potential instantiations of m is (->) ("param" :? T), for example

    :: AccountId
    -> "cursor" :? Maybe Cursor
    -> "order"  :? Maybe Order
    -> "limit"  :? Maybe Int
    -> "param"  :? T
    -> ([TransactionDetails], Cursor)

and in this case ! defaults would fill in "param" :? T as Nothing.

This possibility means that ! defaults tries to inspect m, and this results in the cryptic error message that you see.

A workaround is to give ! defaults a clear signal to stop inspecting the rest of the type:

newtype M m a = M { runM :: m a }
  deriving newtype (Functor, Applicative, Monad)

  accountTransactions
    :: AccountId
    -> "cursor" :? Maybe Cursor
    -> "order"  :? Maybe Order
    -> "limit"  :? Maybe Int
    -> M m ([TransactionDetails], Cursor)

In this case, ! defaults would stumble on M and would not try to inspect the type any further.

@Unisay
Copy link
Author

Unisay commented Sep 25, 2018

Thank you for the clarification!

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

No branches or pull requests

2 participants