Sillyness in the standard libs.

LS, here is a puzzle for you: try converting a System.Posix.Types.EpochTime into either a System.Time.CalendarTime or a Data.Time.Clock.UTCTime without going through read . show or a similar detour through strings. The problem comes up when trying to easily nicely display the access, modification or status change times of a full directory of files, using System.Posix.Files.Filestatus to get at the times. A closely related issue: fromIntegral is in Integral which also requires quotRem. However, the two are semantically quite disjoint. I can *easily* see the semantics of fromIntegral on EpochTime, but not the semantics of quotRem on EpochTime. Having fromIntegral would solve the above puzzle... :) With kind regards, Arthur. -- /\ / | arthurvl@cs.uu.nl | Work like you don't need the money /__\ / | A friend is someone with whom | Love like you have never been hurt / \/__ | you can dare to be yourself | Dance like there's nobody watching

Arthur van Leeuwen wrote:
A closely related issue: fromIntegral is in Integral which also requires quotRem. However, the two are semantically quite disjoint. I can *easily* see the semantics of fromIntegral on EpochTime, but not the semantics of quotRem on EpochTime. Having fromIntegral would solve the above puzzle... :)
As I understand it, it's widely recognised that Haskell's current numeric class hierachy is broken (or at best, not very well chosen), but nobody came up with a better suggestion yet. (By all means, somebody correct me if I'm wrong here...!) Also, that hierachy is in the Haskell Report, so we'll have to wait for Haskell' to fix it for good. (Although you can roll you own right now - if you can think of a better design...)

On Mon, 19 Nov 2007, Andrew Coppin wrote:
Arthur van Leeuwen wrote:
A closely related issue: fromIntegral is in Integral which also requires quotRem. However, the two are semantically quite disjoint. I can *easily* see the semantics of fromIntegral on EpochTime, but not the semantics of quotRem on EpochTime. Having fromIntegral would solve the above puzzle... :)
As I understand it, it's widely recognised that Haskell's current numeric class hierachy is broken (or at best, not very well chosen), but nobody came up with a better suggestion yet.
(By all means, somebody correct me if I'm wrong here...!)
http://www.haskell.org/haskellwiki/Mathematical_prelude_discussion http://www.haskell.org/haskellwiki/Libraries_and_tools/Mathematics#Type_clas...

On 2007-11-19, Andrew Coppin
Arthur van Leeuwen wrote:
A closely related issue: fromIntegral is in Integral which also requires quotRem. However, the two are semantically quite disjoint. I can *easily* see the semantics of fromIntegral on EpochTime, but not the semantics of quotRem on EpochTime. Having fromIntegral would solve the above puzzle... :)
As I understand it, it's widely recognised that Haskell's current numeric class hierachy is broken (or at best, not very well chosen), but nobody came up with a better suggestion yet.
Oh, there are /lots/ of suggestions. Perhaps too many. But this is one area that could really be improved by the use of ATs or MPTCs with fundeps, and that's stalled some of the concrete proposals, as what exactly is happening for Haskell' isn't too clear. -- Aaron Denney -><-

Aaron Denney wrote:
On 2007-11-19, Andrew Coppin
wrote: As I understand it, it's widely recognised that Haskell's current numeric class hierachy is broken (or at best, not very well chosen), but nobody came up with a better suggestion yet.
Oh, there are /lots/ of suggestions. Perhaps too many. But this is one area that could really be improved by the use of ATs or MPTCs with fundeps, and that's stalled some of the concrete proposals, as what exactly is happening for Haskell' isn't too clear.
Er, yes... what *he* said. (I understand there are a couple of similar proposals that have gone nowhere because it's not clear what the best design choice is. E.g., there ought to be some generalisation of the words and lines functions, but there isn't, because nobody can decide on the best generalisation to pick.)

On Nov 19, 2007, at 16:06 , Arthur van Leeuwen wrote:
here is a puzzle for you: try converting a System.Posix.Types.EpochTime into either a System.Time.CalendarTime or a Data.Time.Clock.UTCTime without going through read . show or a similar detour through strings.
fromEnum and/or toEnum are helpful for this kind of thing, and I am occasionally tempted to bind "cast = toEnum . fromEnum" because I need it so much. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On Mon, 19 Nov 2007, Brandon S. Allbery KF8NH wrote:
On Nov 19, 2007, at 16:06 , Arthur van Leeuwen wrote:
here is a puzzle for you: try converting a System.Posix.Types.EpochTime into either a System.Time.CalendarTime or a Data.Time.Clock.UTCTime without going through read . show or a similar detour through strings.
fromEnum and/or toEnum are helpful for this kind of thing, and I am occasionally tempted to bind "cast = toEnum . fromEnum" because I need it so much.
Really? I'd like to know which examples these are. So far I suspected that 'cast' indicates not well chosen types.

On Nov 19, 2007, at 16:50 , Henning Thielemann wrote:
On Mon, 19 Nov 2007, Brandon S. Allbery KF8NH wrote:
fromEnum and/or toEnum are helpful for this kind of thing, and I am occasionally tempted to bind "cast = toEnum . fromEnum" because I need it so much.
Really? I'd like to know which examples these are. So far I suspected that 'cast' indicates not well chosen types.
If so, it's not my types... The specific instance is the one you mentioned about times; fromEnum lets me turn a Foreign.C.Types.CTime (== System.Posix.Types.EpochTime) to an Int (which is commonly just type punning in GHC, since it's the same internal value representation in most (all?) cases), from which I can get to another Foreign.C.Types type with toEnum or to Integer with fromIntegral. (NB: This involves an assumption about CTime; POSIX allows (or used to allow) it to be a floating type in order to allow some non- UNIXlikes to represent POSIX times. But given that CTime is Enum, Foreign.C.Types already violates this; so why isn't it also Integral?) So yes, this is a sign of typing issues in the implementation and (toEnum . fromEnum) is a hack around them. -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

On Nov 19, 2007, at 17:10 , Brandon S. Allbery KF8NH wrote:
CTime; POSIX allows (or used to allow) it to be a floating type in order to allow some non-UNIXlikes to represent POSIX times. But given that CTime is Enum, Foreign.C.Types already violates this; so why isn't it
Hrm, not thinking about that right, Enum works for Floating. Never mind... -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH

Brandon S. Allbery KF8NH wrote:
On Nov 19, 2007, at 16:06 , Arthur van Leeuwen wrote:
here is a puzzle for you: try converting a System.Posix.Types.EpochTime into either a System.Time.CalendarTime or a Data.Time.Clock.UTCTime without going through read . show or a similar detour through strings.
fromEnum and/or toEnum are helpful for this kind of thing, and I am occasionally tempted to bind "cast = toEnum . fromEnum" because I need it so much.
Let's ignore System.Time since it's obsoleted by Data.Time. I just spent a little while trying to solve this puzzle, and it turns out there *is* a right way to do this: for t :: EpochTime, posixSecondsToUTCTime (fromRational (toRational t) :: POSIXTime) You want to go via Data.Time.Clock.POSIXTime, because that's what an EpochTime is. Now, EpochTime does not have an Integral instance, because it is the same as C's time_t type, which is not guaranteed to be an integral type. You have fromEnum, but that would be a hack: there's no guarantee that EpochTime fits in an Int, and if EpochTime is a fractional value you lose information. But you *can* convert to a Rational with toRational, and from there you can get to a POSIXTime with fromRational (also realToFrac would do). It turns out there are good reasons for all this, it just ends up being quite obscure. I'll put the above formula in the docs. Cheers, Simon

On 29-nov-2007, at 14:44, Simon Marlow wrote:
Brandon S. Allbery KF8NH wrote:
On Nov 19, 2007, at 16:06 , Arthur van Leeuwen wrote:
here is a puzzle for you: try converting a System.Posix.Types.EpochTime into either a System.Time.CalendarTime or a Data.Time.Clock.UTCTime without going through read . show or a similar detour through strings. fromEnum and/or toEnum are helpful for this kind of thing, and I am occasionally tempted to bind "cast = toEnum . fromEnum" because I need it so much.
Let's ignore System.Time since it's obsoleted by Data.Time.
Yes. That's what I wanted to do at first. :)
I just spent a little while trying to solve this puzzle, and it turns out there *is* a right way to do this: for t :: EpochTime,
posixSecondsToUTCTime (fromRational (toRational t) :: POSIXTime)
Which, unfortunately, does not work with time-1.1.1 which is in GHC 6.6.1. Going through Rational is the right solution, though. My hackish detour was to use fromIntegral . toInteger . fromEnum
You want to go via Data.Time.Clock.POSIXTime, because that's what an EpochTime is. Now, EpochTime does not have an Integral instance, because it is the same as C's time_t type, which is not guaranteed to be an integral type. You have fromEnum, but that would be a hack: there's no guarantee that EpochTime fits in an Int, and if EpochTime is a fractional value you lose information. But you *can* convert to a Rational with toRational, and from there you can get to a POSIXTime with fromRational (also realToFrac would do).
It turns out there are good reasons for all this, it just ends up being quite obscure. I'll put the above formula in the docs.
Yes, that would be good! Note that both the docs for DiffTime and EpochTime state that they contain seconds, and both are somewhat unclear as to whether they contain any higher precision than whole seconds. With kind regards, Arthur. -- /\ / | arthurvl@cs.uu.nl | Work like you don't need the money /__\ / | A friend is someone with whom | Love like you have never been hurt / \/__ | you can dare to be yourself | Dance like there's nobody watching

On Nov 29, 2007, at 12:12 , Arthur van Leeuwen wrote:
Going through Rational is the right solution, though. My hackish detour was to use fromIntegral . toInteger . fromEnum
?? fromEnum produces an Int, which is an Integral such as fromIntegral requires; why is toInteger needed?
Yes, that would be good! Note that both the docs for DiffTime and EpochTime state that they contain seconds, and both are somewhat unclear as to whether they contain any higher precision than whole seconds.
(a) Whether EpochTime contains higher precision than seconds is system-dependent. (b) Use of a non-Integral type for EpochTime does not necessarily mean it has higher resolution than seconds. (Blame POSIX for both of these. Haskell's System.POSIX must deal, as must any other POSIX-compliant library.) -- brandon s. allbery [solaris,freebsd,perl,pugs,haskell] allbery@kf8nh.com system administrator [openafs,heimdal,too many hats] allbery@ece.cmu.edu electrical and computer engineering, carnegie mellon university KF8NH
participants (7)
-
Aaron Denney
-
Andrew Coppin
-
Arthur van Leeuwen
-
Brandon S. Allbery KF8NH
-
Evan Laforge
-
Henning Thielemann
-
Simon Marlow