Reputation: 8736
I have the following haskell code to expand environment variables in strings (parsing code omitted):
import Control.Monad (liftM)
data Token = Literal String | EnvReference String deriving Show
expandTokens :: (Monad m) => (String -> m (Maybe String)) -> [Token] -> m String
expandTokens getEnv toks = liftM concat (mapM toString toks) where
toString (Literal s) = return s
toString (EnvReference v) = liftM (maybe "" id) (getEnv v)
(it's intended to be used with an IO implementation of getEnv, but I figured it would be nicer for testing if it could be used with any monad)
When I was writing it, I tried to give the nested toString
function an explicit type of:
toString :: Monad m => Token -> m String
But ghc says:
Sample.hs:8:58:
Could not deduce (m ~ m1)
from the context (Monad m)
bound by the type signature for
expandTokens :: Monad m =>
(String -> m (Maybe String)) -> [Token] -> m String
( ... )
I get that the "Monad m" in the expandTokens must necessarily be the exact same m
as in the type of toString
(since it references the getenv
of the containing function), but I can't figure out how to write an explicit type for toString
which respects that - I don't think there's any way to refer to anything in a different type declaration, can it even be done?
Upvotes: 4
Views: 496
Reputation: 20950
I think you're looking for ScopedTypeVariables
. I've never used that, but it looks right.
Upvotes: 4