purescript/purescript-transformers

instance resolution error with MonadReader

cdepillabout opened this issue · 2 comments

In Haskell, the following code works fine:

import Control.Monad.Reader (MonadReader, ask)

data Environment = Production | Test | Development

data Config = Config { environment :: Environment }

class HasConfig a where
    getConfig :: a -> Config

class HasEnvironment a where
    getEnvironment :: a -> Environment

instance HasEnvironment Environment where
    getEnvironment = id

instance HasConfig Config where
    getConfig = id

instance HasEnvironment Config where
    getEnvironment = environment

baseURL :: forall m r . (MonadReader r m, HasEnvironment r) => m String
baseURL = do
    somethingThatHasEnvironment <- ask
    return $ baseURL' (getEnvironment somethingThatHasEnvironment)
  where
    baseURL' :: Environment -> String
    baseURL' Development = "http://127.0.0.1/"
    baseURL' _ = "http://example.com/"

But this similar Purescript code is not working:

module Config where

import Prelude

import Control.Monad.Reader.Class (MonadReader, ask)

data Environment = Production | Test | Development

newtype Config = Config { environment :: Environment }

class HasConfig a where
    getConfig :: a -> Config

class HasEnvironment a where
    getEnvironment :: a -> Environment

instance hasEnvironmentEnvironment :: HasEnvironment Environment where
    getEnvironment = id

instance hasConfigConfig :: HasConfig Config where
    getConfig = id

instance hasEnvironmentConfig :: HasEnvironment Config where
    getEnvironment (Config c) = c.environment

baseURL :: forall m r . (MonadReader r m, HasEnvironment r) => m String
baseURL = do
    somethingThatHasEnvironment <- ask
    return $ baseURL' (getEnvironment somethingThatHasEnvironment)
  where
    baseURL' :: Environment -> String
    baseURL' Development = "http://127.0.0.1/"
    baseURL' _ = "http://example.com/"

I get the following error:

Error in module Config:
No instance found for

  Control.Monad.Reader.Class.MonadReader _38
                                         m28

See https://github.com/purescript/purescript/wiki/Error-Code-NoInstanceFound for more information, or to contribute content related to this error.  

Is this a fundamental limitation with Purescript? Or is this just a bug?

If it is a fundamental limitation with Purescript, it would be nice to have it described on the wiki page: https://github.com/purescript/purescript/wiki/Differences-from-Haskell

I don't imagine it will, but does it work if you do this instead?

    env <- asks getEnvironment
    return $ baseURL' env

It's a temporary limitation of PureScript, due to the inability to express functional dependencies for classes, but purescript/purescript#1580

I think you're completely right. This is caused by a lack of functional dependencies. I didn't even think to check that.

Closing this for now, but hopefully Purescript gets functional dependencies in the near future 😄!