peteofce
peteofce

Reputation: 185

Returning defined type from Either

I have the following type declared:

data Property = Property {mapProperty :: !Object
                      } deriving (Show, Generic)

I am returning that type from the following function:

parseProps :: String -> IO (Either String Property)
parseProps m = fmap property <$> (eitherDecode <$> getMap m)

In the calling function, I have the following:

pr <- liftIO $ parseProps t
let pro = case pr of
        Left err -> fail err
        Right pr -> pr

I get the following error from the line above (Right pr -> pr):

Couldn't match expected type ‘m a’ with actual type ‘Property’ • In the expression: pr In a case alternative: Right pr -> pr In the expression:

    case pr of {
      Left err -> fail err
      Right pr -> pr }

• Relevant bindings include pro :: m a (bound at src/Actor/Master.hs:42:7)

I appreciate any assistance.

Upvotes: 1

Views: 383

Answers (1)

Neil Locketz
Neil Locketz

Reputation: 4318

Your case expression has branches with different types. fail has the type Monad m => String -> m a (so fail err has type Monad m => m a) and pr is a Property.

That's how it gets m a not matching Property.

If you want them to match you need to turn the Property into m Property with return.

Like so:

pr <- liftIO $ parseProps t
pro <- case pr of
    Left err -> fail err
    Right pr -> return pr
...

And do the stuff with pro

Also, as Jon Purdy, and Paul Johnson pointed out in the comments, there is a combinator for this operation called either. So this is a cleaner way to write that:

pr <- liftIO $ parseProps t
pro <- either fail return pr

Upvotes: 1

Related Questions