Reputation: 139
Once again, through some bad, bad programming, I have managed to get myself into an awful situation with types.
Is there any way to convert Either a (IO b)
to IO (Either a b)
? I know, it's not very good programming to get myself into this situation, so I'd also be open to suggestions on how to avoid situations like this.
Upvotes: 2
Views: 641
Reputation: 89053
Sure!
convert :: Either a (IO b) -> IO (Either a b)
convert = either (return . Left) (fmap Right)
Now, if you wanted to convert IO (Either a b)
to Either a (IO b)
, you'd be in trouble, but you don't, so you're ok.
Let's see how convert
works:
either :: (a -> c) -> (b -> c) -> Either a b -> c
, so it takes care of pattern matching for us, figuring out whether we have an a
or an IO b
in your case.a
, we just need to convert it to a IO (Either a b)
. The constructor Left :: a -> Either a b
does the first part, and IO
is a monad, so we can use return
to do Either a b -> IO (Either a b)
.if we have an IO b
, we need to convert it to a IO (Either a b)
. We could do this with do notation:
given iob = do
b <- iob
return . Right $ b
using return . Right
as b -> IO (Either a b)
. But this is exactly the situation that mapM :: Monad m => (a -> b) -> m a -> m b
is for in Monads: given iob = mapM Right iob
. Most people don't use mapM
, though, as it's just the specialization of fmap
to Monads, so we'll use fmap
: given iob = fmap Right iob
, or, pointfree : given = fmap Right
.
Upvotes: 6