How to structure a "speaking" fuzzy clock?

Hello, I am writing a program, the main purpose of which is to print fuzzy time in a casual manner, e.g. "ten to eleven" rather than "10:52". Considering my (lack of) programming experience, I got pretty far with it with the help of D. Fischer and B. Yorgey; you can take a look at the results at https://github.com/caminoix/fuzzytime. However, I also have another purpose, and that is to better learn Haskell. I can't help the feeling that my solution might perhaps work, but is nevertheless ugly, naive or just un-Haskell. Therefore, I would like to ask you how you would structure such a program. I'm not asking for an implementation, just a general idea, such as "a datatype to keep the fuzzy time, deriving Show with a set of separate functions for different languages". Thanks in advance!

On Sunday 16 January 2011 15:16:46, Kamil Stachowski wrote:
Hello,
I am writing a program, the main purpose of which is to print fuzzy time in a casual manner, e.g. "ten to eleven" rather than "10:52". Considering my (lack of) programming experience, I got pretty far with it with the help of D. Fischer and B. Yorgey; you can take a look at the results at https://github.com/caminoix/fuzzytime.
However, I also have another purpose, and that is to better learn Haskell. I can't help the feeling that my solution might perhaps work, but is nevertheless ugly, naive or just un-Haskell.
From a quick glance: not too ugly. In checkFTConf, you have a couple of guards | not (thing `elem` list) which would read better using notElem, | thing `notElem` list checkTimeOk isn't good, better checkTimeOk = case break (== ':') time of (hh, _:mm) -> let h = read hh m = read mm in 0 <= h && h < 24 && 0 <= m && m < 60 _ -> False and to further guard against malformed input, you could also test - not (null hh || null mm) - all isDigit hh && all isDigit mm -- requires import Data,Char The message for precision out of range should contain '<=' instead of '<'. Are you sure you mean humane and not human? In FuzzyTime, maybe it would be better to have the field fzLang be a new datatype Lang instead of a String. In toFuzzyTime, get hour and min(ute) via break (and not per reverse . takeWhile (/= ':') . reverse), like in checkTimeOk
Therefore, I would like to ask you how you would structure such a program.
Hmm, I would need to think about that. What I can say without thinking: I'd use a new datatype for style and lang, and instead of checking the validity of the FuzzyTimeConf before converting to FuzzyTime, I'd write a conversion foo :: FuzzyTimeConf -> Either ErrorMessage FuzzyTime and do the checks during the conversion to not repeat work.
I'm not asking for an implementation, just a general idea, such as "a datatype to keep the fuzzy time, deriving Show with a set of separate functions for different languages".
Thanks in advance!

Oh dear, I didn't actually mean to make you read the whole thing! Thank you
the more!
I'm very happy that you don't think the structure is completely wrong. I was
quite worried about it. But if you say it's not too ugly, I will be able to
sleep at night again :)
Thanks a lot for the tips!
On 16 January 2011 16:14, Daniel Fischer
On Sunday 16 January 2011 15:16:46, Kamil Stachowski wrote:
Hello,
I am writing a program, the main purpose of which is to print fuzzy time in a casual manner, e.g. "ten to eleven" rather than "10:52". Considering my (lack of) programming experience, I got pretty far with it with the help of D. Fischer and B. Yorgey; you can take a look at the results at https://github.com/caminoix/fuzzytime.
However, I also have another purpose, and that is to better learn Haskell. I can't help the feeling that my solution might perhaps work, but is nevertheless ugly, naive or just un-Haskell.
From a quick glance: not too ugly.
In checkFTConf, you have a couple of guards
| not (thing `elem` list)
which would read better using notElem,
| thing `notElem` list
checkTimeOk isn't good, better
checkTimeOk = case break (== ':') time of (hh, _:mm) -> let h = read hh m = read mm in 0 <= h && h < 24 && 0 <= m && m < 60 _ -> False
and to further guard against malformed input, you could also test - not (null hh || null mm) - all isDigit hh && all isDigit mm -- requires import Data,Char
The message for precision out of range should contain '<=' instead of '<'.
Are you sure you mean humane and not human?
In FuzzyTime, maybe it would be better to have the field fzLang be a new datatype Lang instead of a String.
In toFuzzyTime, get hour and min(ute) via break (and not per reverse . takeWhile (/= ':') . reverse), like in checkTimeOk
Therefore, I would like to ask you how you would structure such a program.
Hmm, I would need to think about that. What I can say without thinking:
I'd use a new datatype for style and lang, and instead of checking the validity of the FuzzyTimeConf before converting to FuzzyTime, I'd write a conversion
foo :: FuzzyTimeConf -> Either ErrorMessage FuzzyTime
and do the checks during the conversion to not repeat work.
I'm not asking for an implementation, just a general idea, such as "a datatype to keep the fuzzy time, deriving Show with a set of separate functions for different languages".
Thanks in advance!
participants (2)
-
Daniel Fischer
-
Kamil Stachowski