
michael rice wrote:
Prelude> Just 3 >>= (1+)
Let's check the types. Prelude> :t (>>=) (>>=) :: (Monad m) => m a -> (a -> m b) -> m b Prelude> :t Just 3 Just 3 :: (Num t) => Maybe t Prelude> :t (1 +) (1 +) :: (Num a) => a -> a Renaming the variables in the type of (1 +) gives: (1 +) :: (Num c) => c -> c Since (Just 3) is the first argument of (>>=), we have to unify the types (Maybe t) and (m a). This leads to: m = Maybe t = a Since (1 +) is the second argument of (>>=), we have to unify the types (c -> c) and (a -> m b). This leads to: c = a = m b Since we haven't found any inconsistencies, typechecking succeeded, and we instantiate the types of Just 3, (>>=) and (1 +) to the following types by applying the substituations we found. Just 3 :: Num (Maybe b) => Maybe (Maybe b) (1 +) :: Num (Maybe b) => Maybe b -> Maybe b (>>=) :: Monad Maybe => Maybe (Maybe b) -> (Maybe b -> Maybe b) -> Maybe b And the type of the whole expression is accordingly: Just 3 >>= (1 +) :: (Monad Maybe, Num (Maybe b)) => Maybe b Now ghc looks at the constraints, figures out that Monad Maybe is fine, and complains about Num (Maybe b). Try the fmap function instead, it has the following type: Prelude> :t fmap fmap :: (Functor f) => (a -> b) -> f a -> f b Since every self-respecting Monad is also a Functor, you can use fmap (1 +) (Just 3). Now (a -> b) is unified with (Num a => a -> a), so that the overall type of the function is (Num a => Maybe a) as you would expect. Tillmann