Created
November 17, 2018 23:49
-
-
Save Tehnix/7a70f9c0cf7c5fbf02217218cddac064 to your computer and use it in GitHub Desktop.
Problems with type inference, `HasAwsCredentials env String` and `Member (Reader env) effs`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env stack | |
-- stack --resolver lts-12.16 script --package freer-simple --package lens | |
{-# LANGUAGE TemplateHaskell #-} | |
{-# LANGUAGE MultiParamTypeClasses #-} | |
{-# LANGUAGE FlexibleInstances #-} | |
{-# LANGUAGE FunctionalDependencies #-} | |
{-# LANGUAGE FlexibleContexts #-} | |
{-# LANGUAGE AllowAmbiguousTypes #-} | |
module Test where | |
import Control.Lens (makeLensesWith, camelCaseFields) | |
import Control.Lens ((^.)) | |
import Control.Monad.Freer (Eff, Member, LastMember) | |
import qualified Control.Monad.Freer as Freer | |
import Control.Monad.Freer.Reader (Reader) | |
import qualified Control.Monad.Freer.Reader as Reader | |
data Config = Config | |
{ configAwsCredentials :: String | |
, configOrganization :: String | |
} deriving (Show) | |
makeLensesWith camelCaseFields ''Config | |
test :: (HasAwsCredentials env String, Member (Reader env) effs, LastMember IO effs) => Eff effs String | |
test = do | |
config <- Reader.ask | |
pure $ config ^. awsCredentials | |
main :: IO () | |
main = do | |
let | |
config = Config | |
{ configAwsCredentials = "Test Creds" | |
, configOrganization = "Codetalk" | |
} | |
creds <- Freer.runM . Reader.runReader config $ test | |
putStrLn creds | |
{- | |
λ ~/Desktop ./UsingHasConfig.hs | |
/Users/tehnix/Desktop/UsingHasConfig.hs:27:13: error: | |
• Overlapping instances for Member (Reader s0) effs | |
arising from a use of ‘Reader.ask’ | |
Matching givens (or their superclasses): | |
Member (Reader env) effs | |
bound by the type signature for: | |
test :: forall env (effs :: [* -> *]). | |
(HasAwsCredentials env String, Member (Reader env) effs, | |
LastMember IO effs) => | |
Eff effs String | |
at /Users/tehnix/Desktop/UsingHasConfig.hs:25:1-103 | |
Matching instances: | |
instance (Data.OpenUnion.Internal.FindElem t r, | |
Data.OpenUnion.Internal.IfNotFound t r r) => | |
Member t r | |
-- Defined in ‘Data.OpenUnion.Internal’ | |
(The choice depends on the instantiation of ‘s0, effs’) | |
• In a stmt of a 'do' block: config <- Reader.ask | |
In the expression: | |
do config <- Reader.ask | |
pure $ config ^. awsCredentials | |
In an equation for ‘test’: | |
test | |
= do config <- Reader.ask | |
pure $ config ^. awsCredentials | |
| | |
27 | config <- Reader.ask | |
| ^^^^^^^^^^ | |
/Users/tehnix/Desktop/UsingHasConfig.hs:28:20: error: | |
• Could not deduce (HasAwsCredentials s0 String) | |
arising from a use of ‘awsCredentials’ | |
from the context: (HasAwsCredentials env String, | |
Member (Reader env) effs, LastMember IO effs) | |
bound by the type signature for: | |
test :: forall env (effs :: [* -> *]). | |
(HasAwsCredentials env String, Member (Reader env) effs, | |
LastMember IO effs) => | |
Eff effs String | |
at /Users/tehnix/Desktop/UsingHasConfig.hs:25:1-103 | |
The type variable ‘s0’ is ambiguous | |
Relevant bindings include | |
config :: s0 | |
(bound at /Users/tehnix/Desktop/UsingHasConfig.hs:27:3) | |
These potential instance exist: | |
instance HasAwsCredentials Config String | |
-- Defined at /Users/tehnix/Desktop/UsingHasConfig.hs:23:1 | |
• In the second argument of ‘(^.)’, namely ‘awsCredentials’ | |
In the second argument of ‘($)’, namely ‘config ^. awsCredentials’ | |
In a stmt of a 'do' block: pure $ config ^. awsCredentials | |
| | |
28 | pure $ config ^. awsCredentials | |
| ^^^^^^^^^^^^^^ | |
/Users/tehnix/Desktop/UsingHasConfig.hs:37:51: error: | |
• Ambiguous type variable ‘env0’ arising from a use of ‘test’ | |
prevents the constraint ‘(HasAwsCredentials | |
env0 String)’ from being solved. | |
Probable fix: use a type annotation to specify what ‘env0’ should be. | |
These potential instance exist: | |
instance HasAwsCredentials Config String | |
-- Defined at /Users/tehnix/Desktop/UsingHasConfig.hs:23:1 | |
• In the second argument of ‘($)’, namely ‘test’ | |
In a stmt of a 'do' block: | |
creds <- Freer.runM . Reader.runReader config $ test | |
In the expression: | |
do let config = ... | |
creds <- Freer.runM . Reader.runReader config $ test | |
putStrLn creds | |
| | |
37 | creds <- Freer.runM . Reader.runReader config $ test | |
| ^^^^ | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
For posterity's sake, I'll include the fix here: We needed to enable three more language extensions,
And test becomes,
where you can notice the explicit
forall
and theReader.ask @env
type application. Finally we also added type annotations inmain
, withcreds <- Freer.runM . Reader.runReader config $ test @Config
.