
Hi, I’m trying to write EitherT from first principles and I’m stuck at the first hurdle - Functor. I’m looking for a hint rather than a complete answer :) This is what I have newtype EitherT m a b = EitherT {runEitherT :: m (Either a b)} instance Monad m => Functor (EitherT m a) where ---- fmap :: (a -> b) -> f a -> f b fmap f m = EitherT $ do mv <- runEitherT m case mv of Left _ -> return mv Right rv -> return $ Right (f rv) and here is the compilers view Phrase.hs:31:25: error: • Couldn't match type ‘b’ with ‘a1’ ‘b’ is a rigid type variable bound by the type signature for: fmap :: forall a1 b. (a1 -> b) -> EitherT m a a1 -> EitherT m a b at Phrase.hs:27:5-8 ‘a1’ is a rigid type variable bound by the type signature for: fmap :: forall a1 b. (a1 -> b) -> EitherT m a a1 -> EitherT m a b at Phrase.hs:27:5-8 Expected type: m (Either a a1) Actual type: m (Either a b) • In the expression: return $ Right (f rv) In a case alternative: Right rv -> return $ Right (f rv) In a stmt of a 'do' block: case mv of Left _ -> return mv Right rv -> return $ Right (f rv) • Relevant bindings include rv :: a1 (bound at Phrase.hs:31:19) mv :: Either a a1 (bound at Phrase.hs:28:9) m :: EitherT m a a1 (bound at Phrase.hs:27:12) f :: a1 -> b (bound at Phrase.hs:27:10) fmap :: (a1 -> b) -> EitherT m a a1 -> EitherT m a b (bound at Phrase.hs:27:5) what I think I need to do is fmap over the right value after pulling if out of the monad m by doing mv <- runEitherT m these lines from the compiler are particularly confusing Expected type: m (Either a a1) Actual type: m (Either a b) as I believe f is f:: a1->b So just hints please and I expect I’ll have another duh moment. Thanks Mike

On Thu, Apr 12, 2018 at 11:25:57AM +0100, mike h wrote:
This is what I have
newtype EitherT m a b = EitherT {runEitherT :: m (Either a b)} instance Monad m => Functor (EitherT m a) where ---- fmap :: (a -> b) -> f a -> f b fmap f m = EitherT $ do mv <- runEitherT m case mv of Left _ -> return mv Right rv -> return $ Right (f rv)
Tricky error! The signature for this fmap is: fmap :: (b -> c) -> EitherT m a b -> EitherT m a c The offending line is: Left _ -> return mv You *think* you are returning `Either a c`, but are you really? Type HINTS for more :P -F

You will feel like this was obvious in hindsight.
fmap :: (a -> b) -> f a -> f b
fmap (a -> b) -> EitherT m c a -> EitherT m c b
Now follow the types in your code.
m :: EitherT m c a
mv :: Either c a
return mv :: EitherT m c a -- <- you are back to the wrong type.
How can you instead return EitherT m c b?
On Thu, Apr 12, 2018 at 6:25 AM, mike h
Hi, I’m trying to write EitherT from first principles and I’m stuck at the first hurdle - Functor. I’m looking for a hint rather than a complete answer :)
This is what I have
newtype EitherT m a b = EitherT {runEitherT :: m (Either a b)} instance Monad m => Functor (EitherT m a) where ---- fmap :: (a -> b) -> f a -> f b fmap f m = EitherT $ do mv <- runEitherT m case mv of Left _ -> return mv Right rv -> return $ Right (f rv)
and here is the compilers view Phrase.hs:31:25: error: • Couldn't match type ‘b’ with ‘a1’ ‘b’ is a rigid type variable bound by the type signature for: fmap :: forall a1 b. (a1 -> b) -> EitherT m a a1 -> EitherT m a b at Phrase.hs:27:5-8 ‘a1’ is a rigid type variable bound by the type signature for: fmap :: forall a1 b. (a1 -> b) -> EitherT m a a1 -> EitherT m a b at Phrase.hs:27:5-8 Expected type: m (Either a a1) Actual type: m (Either a b) • In the expression: return $ Right (f rv) In a case alternative: Right rv -> return $ Right (f rv) In a stmt of a 'do' block: case mv of Left _ -> return mv Right rv -> return $ Right (f rv) • Relevant bindings include rv :: a1 (bound at Phrase.hs:31:19) mv :: Either a a1 (bound at Phrase.hs:28:9) m :: EitherT m a a1 (bound at Phrase.hs:27:12) f :: a1 -> b (bound at Phrase.hs:27:10) fmap :: (a1 -> b) -> EitherT m a a1 -> EitherT m a b (bound at Phrase.hs:27:5)
what I think I need to do is fmap over the right value after pulling if out of the monad m by doing mv <- runEitherT m
these lines from the compiler are particularly confusing Expected type: m (Either a a1) Actual type: m (Either a b)
as I believe f is f:: a1->b
So just hints please and I expect I’ll have another duh moment.
Thanks
Mike
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

instance Monad m => Functor (EitherT m a) where fmap f m = EitherT $ do mv <- runEitherT m case mv of Left lv -> return $ Left lv Right rv -> return $ Right (f rv) Thanks all :) I think its correct. The compiler does! Mike
On 12 Apr 2018, at 17:27, David McBride
wrote: You will feel like this was obvious in hindsight.
fmap :: (a -> b) -> f a -> f b fmap (a -> b) -> EitherT m c a -> EitherT m c b
Now follow the types in your code. m :: EitherT m c a mv :: Either c a return mv :: EitherT m c a -- <- you are back to the wrong type.
How can you instead return EitherT m c b?
On Thu, Apr 12, 2018 at 6:25 AM, mike h
mailto:mike_k_houghton@yahoo.co.uk> wrote: Hi, I’m trying to write EitherT from first principles and I’m stuck at the first hurdle - Functor. I’m looking for a hint rather than a complete answer :) This is what I have
newtype EitherT m a b = EitherT {runEitherT :: m (Either a b)} instance Monad m => Functor (EitherT m a) where ---- fmap :: (a -> b) -> f a -> f b fmap f m = EitherT $ do mv <- runEitherT m case mv of Left _ -> return mv Right rv -> return $ Right (f rv)
and here is the compilers view Phrase.hs:31:25: error: • Couldn't match type ‘b’ with ‘a1’ ‘b’ is a rigid type variable bound by the type signature for: fmap :: forall a1 b. (a1 -> b) -> EitherT m a a1 -> EitherT m a b at Phrase.hs:27:5-8 ‘a1’ is a rigid type variable bound by the type signature for: fmap :: forall a1 b. (a1 -> b) -> EitherT m a a1 -> EitherT m a b at Phrase.hs:27:5-8 Expected type: m (Either a a1) Actual type: m (Either a b) • In the expression: return $ Right (f rv) In a case alternative: Right rv -> return $ Right (f rv) In a stmt of a 'do' block: case mv of Left _ -> return mv Right rv -> return $ Right (f rv) • Relevant bindings include rv :: a1 (bound at Phrase.hs:31:19) mv :: Either a a1 (bound at Phrase.hs:28:9) m :: EitherT m a a1 (bound at Phrase.hs:27:12) f :: a1 -> b (bound at Phrase.hs:27:10) fmap :: (a1 -> b) -> EitherT m a a1 -> EitherT m a b (bound at Phrase.hs:27:5)
what I think I need to do is fmap over the right value after pulling if out of the monad m by doing mv <- runEitherT m
these lines from the compiler are particularly confusing Expected type: m (Either a a1) Actual type: m (Either a b)
as I believe f is f:: a1->b
So just hints please and I expect I’ll have another duh moment.
Thanks
Mike
_______________________________________________ Beginners mailing list Beginners@haskell.org mailto:Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Even ‘better’ instance Monad m => Functor (EitherT m a) where fmap f m = EitherT $ runEitherT m >>= \mv -> return $ fmap f mv :)
On 12 Apr 2018, at 21:32, mike h
wrote: instance Monad m => Functor (EitherT m a) where fmap f m = EitherT $ do mv <- runEitherT m case mv of Left lv -> return $ Left lv Right rv -> return $ Right (f rv)
Thanks all :) I think its correct. The compiler does! Mike
On 12 Apr 2018, at 17:27, David McBride
mailto:toad3k@gmail.com> wrote: You will feel like this was obvious in hindsight.
fmap :: (a -> b) -> f a -> f b fmap (a -> b) -> EitherT m c a -> EitherT m c b
Now follow the types in your code. m :: EitherT m c a mv :: Either c a return mv :: EitherT m c a -- <- you are back to the wrong type.
How can you instead return EitherT m c b?
On Thu, Apr 12, 2018 at 6:25 AM, mike h
mailto:mike_k_houghton@yahoo.co.uk> wrote: Hi, I’m trying to write EitherT from first principles and I’m stuck at the first hurdle - Functor. I’m looking for a hint rather than a complete answer :) This is what I have
newtype EitherT m a b = EitherT {runEitherT :: m (Either a b)} instance Monad m => Functor (EitherT m a) where ---- fmap :: (a -> b) -> f a -> f b fmap f m = EitherT $ do mv <- runEitherT m case mv of Left _ -> return mv Right rv -> return $ Right (f rv)
and here is the compilers view Phrase.hs:31:25: error: • Couldn't match type ‘b’ with ‘a1’ ‘b’ is a rigid type variable bound by the type signature for: fmap :: forall a1 b. (a1 -> b) -> EitherT m a a1 -> EitherT m a b at Phrase.hs:27:5-8 ‘a1’ is a rigid type variable bound by the type signature for: fmap :: forall a1 b. (a1 -> b) -> EitherT m a a1 -> EitherT m a b at Phrase.hs:27:5-8 Expected type: m (Either a a1) Actual type: m (Either a b) • In the expression: return $ Right (f rv) In a case alternative: Right rv -> return $ Right (f rv) In a stmt of a 'do' block: case mv of Left _ -> return mv Right rv -> return $ Right (f rv) • Relevant bindings include rv :: a1 (bound at Phrase.hs:31:19) mv :: Either a a1 (bound at Phrase.hs:28:9) m :: EitherT m a a1 (bound at Phrase.hs:27:12) f :: a1 -> b (bound at Phrase.hs:27:10) fmap :: (a1 -> b) -> EitherT m a a1 -> EitherT m a b (bound at Phrase.hs:27:5)
what I think I need to do is fmap over the right value after pulling if out of the monad m by doing mv <- runEitherT m
these lines from the compiler are particularly confusing Expected type: m (Either a a1) Actual type: m (Either a b)
as I believe f is f:: a1->b
So just hints please and I expect I’ll have another duh moment.
Thanks
Mike
_______________________________________________ Beginners mailing list Beginners@haskell.org mailto:Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________ Beginners mailing list Beginners@haskell.org mailto:Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
participants (3)
-
David McBride
-
Francesco Ariis
-
mike h