How to pass only one side of either as a parameter Haskell

Viewed 510

One of my functions returns either:

parse :: Int -> String -> Either String JsonLikeValue

And other takes JsonLikeValue as a parameter:

convert :: Int -> JsonLikeValue -> Either InvalidState To

JsonLikeValue is custom data type:

data JsonLikeValue = JLString String | JLInt Int | JLArray [JsonLikeValue] deriving (Show, Eq)

And when I call:

convert num (parse size message)

it gives following:

Couldn't match expected type ‘JsonLikeValue’
                  with actual type ‘Either String JsonLikeValue’

How can this be avoided and only right side be passed as argument? Thanks in advance :)

EDIT: solution marked as answer is very helpful since it takes into consideration all possible outcomes, and as I'm not an expert but still, looks more professional, so it is very important to take a look at it.

But what was enough to solve the required extraction was:

extractValue :: Either String JsonLikeValue -> JsonLikeValue
extractValue a = case a of
        Left e -> JLArray []
        Right r -> r 

where in case of Right it returns only value, and in case of Left it returns something of required data type. Note that this only works if you're 100% sure that argument will return Right value. Otherwise, check answer below.

Another good notice in comments is to use fromRight from Data.Either

1 Answers

The first problem is that we need to return something in case the parse value returns a Left … value. We can for example make a function that combines the two "errors" with:

myfunction :: Int -> Int -> String -> Either (Either String InvalidState) To
myfunction = …

We can make use of pattern matching to unpack the value in case of a Right and then use the convert function, like:

myfunction :: Int -> Int -> String -> Either (Either String InvalidState) To
myfunction size num message = go (parse size message)
    where go (Left e) = Left (Left e)
          go (Right jlv) = pp (convert num jlv)
          pp (Left e) = Left (Right e)
          pp (Right r) = Right r

Here go thus inspects the result of the parse size message value, and in case it is a Left e, we return Left (Left e). If it is a Right jlv (with jlv the JsonLikeValue wrapped in it), we thus call convert num jlv.

We still need to post-process the result with the pp function. The convert num jlv will have type Either InvalidState To, and we need to convert it to an Either (Either String InvalidState) To. We do that by converting a Left e to a Left (Right e), and a Right r to a Right r. Note that the Right in the body is a data constructor of the Either (Either String InvalidState) To type, wheras the Right in the head is a data constructor of the Either InvalidState To, so the two are not the same.

Related