Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9021991
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 16, 20262026-06-16T05:23:27+00:00 2026-06-16T05:23:27+00:00

I have a data type data Time = Time {hour :: Int, minute ::

  • 0

I have a data type

data Time = Time {hour :: Int,
                  minute :: Int
                 }

for which i have defined the instance of Show as being

instance Show Time where
  show (Time hour minute) = (if hour > 10
                             then (show hour)
                             else ("0" ++ show hour))
                            ++ ":" ++
                            (if minute > 10
                             then (show minute)
                             else ("0" ++ show minute))

which prints out times in a format of 07:09.

Now, there should be symmetry between Show and Read, so after reading (but not truly (i think) understanding) this and this, and reading the documentation, i have come up with the following code:

instance Read Time where
  readsPrec _ input =
    let hourPart = takeWhile (/= ':')
        minutePart = tail . dropWhile (/= ':')
    in (\str -> [(newTime
                  (read (hourPart str) :: Int)
                  (read (minutePart str) :: Int), "")]) input

This works, but the "" part makes it seem wrong. So my question ends up being:

Can anyone explain to me the correct way to implement Read to parse "07:09" into newTime 7 9 and/or show me?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-16T05:23:28+00:00Added an answer on June 16, 2026 at 5:23 am

    I’ll use isDigit and keep your definition of Time.

    import Data.Char (isDigit)
    
    data Time = Time {hour :: Int,
                      minute :: Int
                     }
    

    You used but didn’t define newTime, so I wrote one myself so my code compiles!

    newTime :: Int -> Int -> Time
    newTime h m | between 0 23 h && between 0 59 m = Time h m
                | otherwise = error "newTime: hours must be in range 0-23 and minutes 0-59"
         where between low high val = low <= val && val <= high
    

    Firstly, your show instance is a little wrong because show $ Time 10 10 gives "010:010"

    instance Show Time where
      show (Time hour minute) = (if hour > 9       -- oops
                                 then (show hour)
                                 else ("0" ++ show hour))
                                ++ ":" ++
                                (if minute > 9     -- oops
                                 then (show minute)
                                 else ("0" ++ show minute))
    

    Let’s have a look at readsPrec:

    *Main> :i readsPrec
    class Read a where
      readsPrec :: Int -> ReadS a
      ...
        -- Defined in GHC.Read
    *Main> :i ReadS
    type ReadS a = String -> [(a, String)]
        -- Defined in Text.ParserCombinators.ReadP
    

    That’s a parser – it should return the unmatched remaining string instead of just "", so you’re right that the "" is wrong:

    *Main> read "03:22" :: Time
    03:22
    *Main> read "[23:34,23:12,03:22]" :: [Time]
    *** Exception: Prelude.read: no parse
    

    It can’t parse it because you threw away the ,23:12,03:22] in the first read.

    Let’s refactor that a bit to eat the input as we go along:

    instance Read Time where
      readsPrec _ input =
        let (hours,rest1) = span isDigit input
            hour = read hours :: Int
            (c:rest2) = rest1
            (mins,rest3) = splitAt 2 rest2
            minute = read mins :: Int
            in
          if c==':' && all isDigit mins && length mins == 2 then -- it looks valid
             [(newTime hour minute,rest3)]
           else []                      -- don't give any parse if it was invalid
    

    Gives for example

    Main> read "[23:34,23:12,03:22]" :: [Time]
    [23:34,23:12,03:22]
    *Main> read "34:76" :: Time
    *** Exception: Prelude.read: no parse
    

    It does, however, allow “3:45” and interprets it as “03:45”. I’m not sure that’s a good idea, so perhaps we could add another test length hours == 2.


    I’m going off all this split and span stuff if we’re doing it this way, so maybe I’d prefer:

    instance Read Time where
      readsPrec _ (h1:h2:':':m1:m2:therest) =
        let hour   = read [h1,h2] :: Int  -- lazily doesn't get evaluated unless valid
            minute = read [m1,m2] :: Int
            in
          if all isDigit [h1,h2,m1,m2] then -- it looks valid
             [(newTime hour minute,therest)]
           else []                      -- don't give any parse if it was invalid
      readsPrec _ _ = []                -- don't give any parse if it was invalid
    

    Which actually seems cleaner and simpler to me.

    This time it doesn’t allow "3:45":

    *Main> read "3:40" :: Time
    *** Exception: Prelude.read: no parse
    *Main> read "03:40" :: Time
    03:40
    *Main> read "[03:40,02:10]" :: [Time]
    [03:40,02:10]
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a mysql table field set as time type which stores data in
I have a universal data type, which is passed by value, but does not
I have data defined like the ff.: import Data.Time.Clock data D = D {
I have data structure which stores POD-structs (each instantiation stores a single type only,
I have a service which polls every hour attempts to sync data automatically to
I have a field say DueDate having a date/time data type. I create a
Does Java have a data type that represents a period of time eg 34
I have a data type that contains a set and a method that expects
The table columns have the data type BLOB and CLOB. What are the corresponding
I know that SQL Server does not have boolean data type and your best

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.