I'm trying to understand why purescript
is unable to properly infer type for map
parameter in this simple code:
maybeInc :: String -> StateT (Maybe Int) Identity Unit
maybeInc "a" = modify $ map (1 +)
maybeInc _ = return unit
Here is my error message:
No type class instance was found for Control.Monad.State.Class.MonadState (_0 Int) (StateT (Maybe Int) Identity) The instance head contains unknown type variables. Consider adding a type annotation.
However, it works if I specify the type manually:
maybeInc "a" = modify $ \(m :: Maybe Int) -> map (1 +) m
Why it doesn't want to infer this type automatically even it's already provided in function signature?
The current compiler has no way of modeling functional dependencies, which are used in Haskell and the mtl
library to capture the relationship between the two type arguments in MonadState
.
This means that the compiler can't figure out that the two state types have to be the same (that is, if we find an instance of MonadState
for StateT (Maybe Int) Identity
, the state type is forced to be Maybe Int
).
For now, one solution is to add a type annotation:
maybeInc :: String -> StateT (Maybe Int) Identity Unit
maybeInc "a" = modify modifier
where
modifier :: Maybe Int -> Maybe Int
modifier = map (1 +)
maybeInc _ = return unit