4

I have the following type:

data Color = Red
           | Yellow
           | Green
           | ...

I want a function mapping string representation to specific Color.

str2Color :: String -> Color

str2Color "Red": Red
str2Color "Yellow": Yellow
str2Color "Green": Green

I could enumerate all strings, but problem is the list of all colors is very long. Is there any simpler way?

ps: Let's assume all input strings have a corresponding Color, for ease of exposition.

2
  • 3
    You can make a deriving Read from the Color type, then you can use read :: String -> Color to convert a string to the corresponding Color. Commented Aug 24, 2020 at 22:49
  • @WillemVanOnsem Works like a charm. Thanks. Commented Aug 24, 2020 at 22:57

1 Answer 1

5

As @WillemVanOnsem noted in a comment, you can have the compiler derive a Read instance for your Color type:

data Color = Red | Yellow | Blue
  deriving (Read, Show)

which then makes available the function:

read :: String -> Color

to convert a String to the corresponding Color.

Full example:

data Color = Red | Yellow | Blue
  deriving (Read, Show)

main = do
  print (read "Red" :: Color)
  print (read "Blue" :: Color)
  

read throws an exception if the String isn’t a valid Color. To handle this case yourself, you can use Text.Read.readMaybe :: (Read a) => String -> Maybe a and pattern-match on the result.

import Text.Read (readMaybe)

main = do
  print (readMaybe "Red" :: Maybe Color)    -- Just Red
  print (readMaybe "Beans" :: Maybe Color)  -- Nothing
  s <- getLine
  case readMaybe s of
    Just color -> print (color :: Color)
    Nothing -> putStrLn ("Invalid color: '" ++ s ++ "'")
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.