Skip to content

Instantly share code, notes, and snippets.

@EncodePanda
Last active November 13, 2018 11:22
Show Gist options
  • Select an option

  • Save EncodePanda/978fa5a298f0e4ddd1ce6b894eed372f to your computer and use it in GitHub Desktop.

Select an option

Save EncodePanda/978fa5a298f0e4ddd1ce6b894eed372f to your computer and use it in GitHub Desktop.

I have a function that looks like this

app ::
     ( MonadReader Config m
     , Weather m
     , Console m
     , MonadError Error m
     , MonadState Requests m
     )
  => m ()
app = do
  host <- fetchHost
  port <- fetchPort
  pLine $ "Running using service " ++ host ++ ":" ++ show port
  forever askAndFetch

it used to run on a StateT ReaderT ExceptT IO and everything was fine

main = do
  let config = Config "host" 8080
  (runExceptT $ runReaderT (evalStateT app Map.empty) config ) >>= handleErrors
    where
      handleErrors :: Either Error () -> IO ()

but know I want to remove StateT and provide the MonadState via ReaderT TVar like this

instance (MonadIO m, MonadReader (TVar s) m) => (MonadState s m) where
  put s = void $ ask >>= (\tv -> liftIO $ atomically $ swapTVar tv s)
  get = ask >>= (liftIO.readTVarIO)

but when I get to the main function, which I changed to look like

main = do
  let config = Config "host" 8080
  tvar <- newTVarIO (Map.empty :: Requests)
  (runExceptT $ runReaderT (runReaderT app config) tvar) >>= handleErrors
    where
      handleErrors :: Either Error () -> IO ()```

I get

Overlapping instances for MonadState
                                  Requests
                                  (ReaderT Config (ReaderT (TVar Requests) (ExceptT Error IO)))
        arising from a use of 'app'
      Matching instances:
        instance [safe] (MonadIO m, MonadReader (TVar s) m) =>
                        MonadState s m
          -- Defined in 'TaglesFinalApp'
        ...plus one instance involving out-of-scope types
          instance [safe] MonadState s m => MonadState s (ReaderT r m)
            -- Defined in 'Control.Monad.State.Class'

Why does it look up for the instance in Control.Monad.State.Class, I’m not asking it to 🙂 btw my imports

import Control.Monad.Trans.Except
import Control.Concurrent.STM.TVar
import qualified Data.Map.Strict as Map
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment