What you are trying to do boils down to the following:
f :: Either a Bool -> Either a () f (Right _) = Right () f left = left
with an error:
foo.hs:3:7: Couldn't match type 'Bool' with '()' Expected type: Either a () Actual type: Either a Bool In the expression: left In an equation for 'f': f left = left Failed, modules loaded: none.
left bound to the function argument. Thus, the checking type knows its type Either a Bool . Then it is used as the return value. We know from type f :: Either a Bool -> Either a () that the return value must be of type Either a () . If left is a valid return value, it must match the return type f . So, Either a () should be equal to Either a Bool ; this is not so, therefore, the checking type rejects the program.
In turn, this is basically the same problem as this:
λ let l = Left () :: Either () () l :: Either () () λ l Left () it :: Either () () λ l :: Either () Bool <interactive>:10:1: Couldn't match type '()' with 'Bool' Expected type: Either () Bool Actual type: Either () () In the expression: l :: Either () Bool In an equation for 'it': it = l :: Either () Bool
We gave l binding and a type, and then tried to use it as another type. This is invalid (and passing it through id will not change its type either). Although Left () also valid source code for a value of type Either () Bool , this does not mean that a specific value, known as type Either () () , that can be defined with the source text of Left () , can be used as if it were of type Either () Bool .
If you have a polymorphic value, you can do this:
λ let l = Left () l :: Either () b λ l :: Either () () Left () it :: Either () () λ l :: Either () Bool Left () it :: Either () Bool
Note that the original value of l here was polymorphic in b ; it can be used as Either () b for any b.
But your fmap case looks a little different. Function fmap is polymorphic in b , but the value of its argument is "within polymorphism"; at the point where you have an argument, type b was chosen by the specific type as the fmap caller, so it is "some unknown type that could have anything," and not "any type that I feel like a choice." It is not possible to somehow convert a value of type Either ab to a value of type Either ac , so you need to extract the value of a and then create Either ac containing it.