jazaniac
jazaniac

Reputation: 145

how to get a function in Haskell to return more than one type using a data type?

So in my code I have the data type Token declared as:

data Token = Char | Int
deriving (Show,Eq,Ord)

and a function readIfNumber declared as

readIfNumber :: Char -> Token 
readIfNumber a 
    | isDigit a = Token (digitToInt a)
    | otherwise = Token a

but when I try to compile, the console returns an error of "expecting type Token, but got Char" or "expecting Token, but got Int" when an Int should be viewed as a Token, according to my declaration of Token. What am I doing wrong here?

Upvotes: 2

Views: 132

Answers (1)

leftaroundabout
leftaroundabout

Reputation: 120751

In a variant type, you always need to be explicit about which of the options you take. I.e. you need to “label” the two branches unambiguously, with constructors. Like,

data Token = CharToken Char | IntToken Int

When actually building a token from either a char or int, you thereto wrap it in the suitable constructor:

readIfNumber a 
 | isDigit a = IntToken $ digitToInt a
 | otherwise = CharToken a

The reason this is required? Well, Haskell has full type erasure, i.e. types are completely traced, decided and optimised at compile time. At runtime, you wouldn't know whether the contained type was a char or int. Sometimes that's ok, namely when you have polymorphic actions. For example, length really doesn't care what the type of the elements contained in a list is, as it only deals with the structure of the list.

In this case however, somebody who receives a Token will need to know whether it's a char or int, to properly process it further. Hence the need to tag which type is contained.

Upvotes: 7

Related Questions