
Imants Cekusins, Well using monad transformers like that is a fairly common design pattern in Haskell, so I think you should get used to it ;) But you don't really need to understand monad transformers in depth just to use the ig library, it appears that all actions defined there have a type like :: (MonadBaseControl IO m, MonadResource m) => _ some arguments _ -> InstagramT m _result_ The smallest monad that satisfies both (MonadBaseControl IO m) and (MonadResource m) is just (ResourceT IO), so the code suggested by Bob Ippolito token <- runResourceT . runInstagramT credentials manager $ getUserAccessTokenURL2 redirectUrl code works, because "getUserAccessTokenURL2 redirectUrl code" has type "InstagramT (ResourceT IO) OAuthToken". It is one of Haskell's features that the actual concrete type of an expression is inferred according to the context in which it appears, and thus may vary. * The whole thing starts with the type "MonadBaseControl IO m, MonadResource m => InstagramT m OAuthToken" * runInstagramT strips the InstagramT layer, leaving "MonadBaseControl IO m, MonadResource m =>m OAuthToken" * runResourceT has type "MonadBaseControl IO m => ResourceT m a -> m a", so Haskell infers that the "m OAuthToken" above is actually "MonadBaseControl IO m => ResourceT m OAuthToken". The satisfaction of the MonadResource constraint is provided by the ResouceT layer itself, which is stripped by runResourceT then. * at the end, Haskell is left with "MonadBaseControl IO m => m OAuthToken", which it tries to unify with "IO something", because you're using it in the do block of main, that must have the type IO () in the end. As "IO OAuthToken" does satisfy this constraint, everything is fine. The library uses type classes instead of this concrete type, because some users might want to supply a more complicated monad transformer stack than that, but of course you don't actually have to do this. Best regards, Marcin Mrotek