0
votes

I need to return for example either an integer or a Boolean in a recursive function.

An example code of my problem:

findInt :: [Int] -> Either Int Bool
findInt (x:xs) =
     if x == 1 then x
     else False : findInt xs

Then the error says couldn't match expected type "Either Int Bool" with actual type "Int". But I want to check whether the element is in this list and if it does it will return the element and tell me if it's not by returning a Boolean.

3
It would be easier to answer your question if you added some examples of inputs and the corresponding outputs that you expect, like findInt [...] == ... for various cases. - Jon Purdy
As it is, your function says “given a list of at least one element, if the first element is the integer 1, then return that integer, otherwise return a list beginning with the boolean False followed by the result of callling findInt on the remainder of the list; when given an empy list, raise an error”, which doesn’t make much sense, so it’s difficult to determine what you’re trying to do in order to help you. - Jon Purdy

3 Answers

3
votes

Your function as given has no type: x :: Int and (False : _) :: [Bool], and these two types can't be unified (read :: as "has a type").

Tweaked,

findInt (x:xs) =
     if x == 1 then Left x
     else Right False : findInt xs

it still has no type: Left x :: Either Int b and (Right False : _) :: [Either a Bool], and these two types can't be unified either.

But

findInt :: [Int] -> Either Int Bool
findInt (x:xs) =
     if x == 1 then Left x
     else findInt xs
findInt [] = Right False

has a type, because Left x :: Either Int b and Right False :: Either a Bool, and these two types can be unified:

        Either Int b
        Either a   Bool
       -----------------      a ~ Int , b ~ Bool
        Either Int Bool

The unified type is indeed Either Int Bool, as the type signature specifies.

4
votes

If you have a look at the Either type, you'll see that it has two constructors, Left and Right. In order to construct a value of the Either type, you need to use one of the constructors. e.g.

if x == 1 then Left x

Specifically, Left is used to construct the first type of the Either type (Int in this case), and Right is used for the second type (Bool in this case).

1
votes

Since you never use True in your output, your use of Either Int Bool is isomorphic to Maybe Int:

a2b :: Either Int Bool -> Maybe Int
a2b (Right x) = Just x
a2b (Left x) = Nothing

b2a :: Maybe Int -> Either Int Bool
b2a (Just x) -> Right x
b2a Nothing -> Left False

As such, I would just use Maybe Int to simplify your function.

findInt :: [Int] -> Maybe Int
findInt [] = Nothing
findInt (x:xs) = if x == 1 then Just x else findInt xs