Jeff Shaw | 27 Mar 16:17 2013
Picon

The numeric c types are (effectively) integral, too.

This query is regarding Foreign.C.Types.

Now that the constructors for CClock, CTime, CUSeconds, and CSUSeconds are exposed, it's become clear that these are Ints or Words. Technically on some architectures they could be floating point, but I would bet that on all architectures that Haskell is ever used on, none of these are floating point types. Adding Bounded, Enum, Integral, and Bits instances to the "numeric" types would break nothing and ease situations such as this:

roundTo :: CTime -> CTime -> CTime
roundTo a b = (a `div` b) * b

This works right now, but requires a trivial Integral class be written for every program that wants to do it.

instance Integral CTime where
  quot (CTime a) (CTime b) = CTime (a `quot` b)
  rem (CTime a) (CTime b) = CTime (a `rem` b)
  div (CTime a) (CTime b) = CTime (a `div` b)
  mod (CTime a) (CTime b) = CTime (a `mod` b)
  quotRem (CTime n) (CTime d) = (\(d,m) -> (CTime d, CTime m)) (quotRem n d)
  divMod (CTime n) (CTime d) = (\(d,m) -> (CTime d, CTime m)) (divMod n d)
  toInteger (CTime t) = toInteger t

I think this and the other trivial instances should just go right into Foreign.C.Types for all the "numeric" types in Foreign.C.Types. Any thoughts to the contrary?

Jeff
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Henning Thielemann | 27 Mar 16:30 2013
Picon

Re: The numeric c types are (effectively) integral, too.


On Wed, 27 Mar 2013, Jeff Shaw wrote:

> roundTo :: CTime -> CTime -> CTime
> roundTo a b = (a `div` b) * b
> 
> This works right now, but requires a trivial Integral class be written for every program that wants to do
> it.

Writing orphan instances is generally a bad idea. Instead you could put 
your roundTo function into a nice package and import it everywhere. I 
don't think that an Integral instance is the right way to go, since it 
would imply the signature:

div :: CTime -> CTime -> CTime

and the quotient of two time values is not a time.
Jeff Shaw | 27 Mar 17:08 2013
Picon

Re: The numeric c types are (effectively) integral, too.

On Wednesday, March 27, 2013 11:30:24 AM, Henning Thielemann wrote:

> Writing orphan instances is generally a bad idea. Instead you could
> put your roundTo function into a nice package and import it
> everywhere.

Yup! So let's put the Integral, etc. instances right in 
Foreign.C.Types. That way no one will make the mistake you're accusing 
me of.

> I don't think that an Integral instance is the right way
> to go, since it would imply the signature:
>
> div :: CTime -> CTime -> CTime
>
> and the quotient of two time values is not a time.

That is irrelevant. CTime is a newtype of an integer type, and the 
quotient of two integers is an integer. Foreign.C.Types certainly 
doesn't have a problem dividing even stranger things, like graphemes by 
graphemes.

I'm quite sure that the reason that CTime doesn't have an Integral 
instance is that technically the C spec allows time_t to be a float. 
However, since time_t is practically always an integer value, we should 
expose that by defining the Integral instance right in Foreign.C.Types.

I looked through the header files for FreeBSD's platforms, and time_t 
is always an __int32 or __int64. Maybe Linux or NetBSD can provide an 
exception.

Jeff
Henning Thielemann | 27 Mar 17:16 2013
Picon

Re: The numeric c types are (effectively) integral, too.


On Wed, 27 Mar 2013, Jeff Shaw wrote:

> On Wednesday, March 27, 2013 11:30:24 AM, Henning Thielemann wrote:
>
>> I don't think that an Integral instance is the right way
>> to go, since it would imply the signature:
>> 
>> div :: CTime -> CTime -> CTime
>> 
>> and the quotient of two time values is not a time.
>
> That is irrelevant.

It is highly relevant and certainly a major difference between Haskell and 
C. A time can be represented with any unit and with either integer or 
floating or fixed-point numbers. Actually, the integer can always be read 
as fixed-point number, since the unit is somehow arbitrary. The quotient 
of two time values is not a time value but a scalar value and it is good 
if Haskell alerts you when you mix them up.
Jeff Shaw | 27 Mar 17:55 2013
Picon

Re: The numeric c types are (effectively) integral, too.

On 3/27/2013 12:16 PM, Henning Thielemann wrote:
>
> On Wed, 27 Mar 2013, Jeff Shaw wrote:
>
>> On Wednesday, March 27, 2013 11:30:24 AM, Henning Thielemann wrote:
>>
>>> I don't think that an Integral instance is the right way
>>> to go, since it would imply the signature:
>>>
>>> div :: CTime -> CTime -> CTime
>>>
>>> and the quotient of two time values is not a time.
>>
>> That is irrelevant.
>
> It is highly relevant and certainly a major difference between Haskell 
> and C. A time can be represented with any unit and with either integer 
> or floating or fixed-point numbers. Actually, the integer can always 
> be read as fixed-point number, since the unit is somehow arbitrary. 
> The quotient of two time values is not a time value but a scalar value 
> and it is good if Haskell alerts you when you mix them up.
The functionality you want is located in Data.Time.Clock. 
Foreign.C.Types is for working with C values, which do permit integer 
division on time_t when it happens to be an integer, which as far as 
Haskell is concerned, is always.

Your argument can also be used to say that C values with the unit 
"grapheme" shouldn't be allowed division, either. However, they are. Do 
you think we should remove the Integral instance for CChar? What about 
the Bounded and Bits instances? Data.Char.Char only has Bounded.

Furthermore, CTime is an instance of Num, which means that you can do 
multiplication on CTime values. Do you think we should remove that? 
After all, Time * Time is Time ^2, not Time.

Jeff
Henning Thielemann | 27 Mar 23:20 2013
Picon

Re: The numeric c types are (effectively) integral, too.


On Wed, 27 Mar 2013, Jeff Shaw wrote:

> Your argument can also be used to say that C values with the unit "grapheme" 
> shouldn't be allowed division, either. However, they are. Do you think we 
> should remove the Integral instance for CChar?

Would be better.

> Furthermore, CTime is an instance of Num, which means that you can do 
> multiplication on CTime values. Do you think we should remove that? After 
> all, Time * Time is Time ^2, not Time.

If someone had asked me, I would have reject it.
Krzysztof Skrzętnicki | 27 Mar 21:35 2013
Picon

Re: The numeric c types are (effectively) integral, too.

I second this. The fact that time_t is sometimes uint or anything else is simply implementation detail (unless one can point to relevant standards that say otherwise). If one wishes to bet on this being true then simple private newtype with proper instances seems like the way to go. But it feels insecure to do otherwise.


Cheers,
Krzysztof Skrzętnicki

On Wed, Mar 27, 2013 at 5:16 PM, Henning Thielemann <lemming <at> henning-thielemann.de> wrote:

On Wed, 27 Mar 2013, Jeff Shaw wrote:

On Wednesday, March 27, 2013 11:30:24 AM, Henning Thielemann wrote:

I don't think that an Integral instance is the right way
to go, since it would imply the signature:

div :: CTime -> CTime -> CTime

and the quotient of two time values is not a time.

That is irrelevant.

It is highly relevant and certainly a major difference between Haskell and C. A time can be represented with any unit and with either integer or floating or fixed-point numbers. Actually, the integer can always be read as fixed-point number, since the unit is somehow arbitrary. The quotient of two time values is not a time value but a scalar value and it is good if Haskell alerts you when you mix them up.


_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Jon Fairbairn | 28 Mar 11:00 2013
X-Face
Picon
Picon

Re: The numeric c types are (effectively) integral, too.

Krzysztof Skrzętnicki <gtener <at> gmail.com> writes:

> I second this. The fact that time_t is sometimes uint or anything else is
> simply implementation detail (unless one can point to relevant standards
> that say otherwise). If one wishes to bet on this being true then simple
> private newtype with proper instances seems like the way to go. But it
> feels insecure to do otherwise.

+1
--

-- 
Jón Fairbairn                                 Jon.Fairbairn <at> cl.cam.ac.uk

_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
wren ng thornton | 28 Mar 19:10 2013

Re: The numeric c types are (effectively) integral, too.

On 3/27/13 12:16 PM, Henning Thielemann wrote:
>
> On Wed, 27 Mar 2013, Jeff Shaw wrote:
>
>> On Wednesday, March 27, 2013 11:30:24 AM, Henning Thielemann wrote:
>>
>>> I don't think that an Integral instance is the right way
>>> to go, since it would imply the signature:
>>>
>>> div :: CTime -> CTime -> CTime
>>>
>>> and the quotient of two time values is not a time.
>>
>> That is irrelevant.
>
> It is highly relevant and certainly a major difference between Haskell
> and C. A time can be represented with any unit and with either integer
> or floating or fixed-point numbers. Actually, the integer can always be
> read as fixed-point number, since the unit is somehow arbitrary. The
> quotient of two time values is not a time value but a scalar value and
> it is good if Haskell alerts you when you mix them up.

+1.

--

-- 
Live well,
~wren
Brandon Allbery | 27 Mar 17:16 2013
Picon

Re: The numeric c types are (effectively) integral, too.

On Wed, Mar 27, 2013 at 12:08 PM, Jeff Shaw <shawjef3 <at> gmail.com> wrote:
I looked through the header files for FreeBSD's platforms, and time_t is always an __int32 or __int64. Maybe Linux or NetBSD can provide an exception.

There have been times when it was a struct made of multiple integral values, also.

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b <at> gmail.com                                  ballbery <at> sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Jeff Shaw | 27 Mar 17:58 2013
Picon

Re: The numeric c types are (effectively) integral, too.

On 3/27/2013 12:16 PM, Brandon Allbery wrote:
On Wed, Mar 27, 2013 at 12:08 PM, Jeff Shaw <shawjef3 <at> gmail.com> wrote:
I looked through the header files for FreeBSD's platforms, and time_t is always an __int32 or __int64. Maybe Linux or NetBSD can provide an exception.

There have been times when it was a struct made of multiple integral values, also.

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b <at> gmail.com                                  ballbery <at> sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
That's fascinating. If we're concerned with those cases in base, we should probably remove at least the Enum, Num, and Real instances from CTime, or provide special cases. I imagine Show and Read become nontrivial, as well.

Jeff
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Jason Dusek | 28 Mar 11:32 2013
Picon

Re: The numeric c types are (effectively) integral, too.

2013/3/27 Henning Thielemann <lemming <at> henning-thielemann.de>:
> Writing orphan instances is generally a bad idea. Instead you could put your
> roundTo function into a nice package and import it everywhere. I don't think
> that an Integral instance is the right way to go, since it would imply the
> signature:
>
> div :: CTime -> CTime -> CTime
>
> and the quotient of two time values is not a time.

One way to think of it is, CTime is time and should follow the
rules of the time. Another way is, CTime is a C type and should
follow the rules of C types.  The latter perspective seems more
appropriate for Foreign.C.* (we are likely to seek out some
other module for modelling time).

--
Jason Dusek
pgp // solidsnack // C1EBC57DC55144F35460C8DF1FD4C6C1FED18A2B
David Virebayre | 28 Mar 13:20 2013
Picon

Re: The numeric c types are (effectively) integral, too.

2013/3/28 Jason Dusek <jason.dusek <at> gmail.com>

> One way to think of it is, CTime is time and should follow the
> rules of the time. Another way is, CTime is a C type and should
> follow the rules of C types.  The latter perspective seems more
> appropriate for Foreign.C.* (we are likely to seek out some
> other module for modelling time).

I agree that the latter perspective seems more appropriate, however,
according to Wikipedia :

ISO C defines time_t as an arithmetic type, but does not specify any
particular type, range, resolution, or encoding for it. Also
unspecified are the meanings of arithmetic operations applied to time
values.

So, even if, in C, you may be able to apply arithmetic operations to a
time_t, you can't be sure it makes sense, so you shouldn't normally do
it. Why then, make it easier in Foreign.C to do something meaningless
? That's just begging to shoot yourself in the foot.
Brandon Allbery | 28 Mar 14:46 2013
Picon

Re: The numeric c types are (effectively) integral, too.

On Thu, Mar 28, 2013 at 8:20 AM, David Virebayre <dav.vire+haskell <at> gmail.com> wrote:
So, even if, in C, you may be able to apply arithmetic operations to a
time_t, you can't be sure it makes sense, so you shouldn't normally do
it. Why then, make it easier in Foreign.C to do something meaningless
? That's just begging to shoot yourself in the foot.

Because you need to convert it from a foreign representation, which may require arbitrary math depending on the details of that representation. And, while there may not be a strict meaning applied by the standard, there *is* a platform-dependent strict meaning (else times would be useless) *and* the conversion between the FFI and Haskell representations will need to know that platform-dependent meaning so that it can do a meaningful conversion. 

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b <at> gmail.com                                  ballbery <at> sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
David Virebayre | 29 Mar 13:03 2013
Picon

Re: The numeric c types are (effectively) integral, too.

2013/3/28 Brandon Allbery <allbery.b <at> gmail.com>:

> Because you need to convert it from a foreign representation, which may
> require arbitrary math depending on the details of that representation. And,
> while there may not be a strict meaning applied by the standard, there *is*
> a platform-dependent strict meaning (else times would be useless) *and* the
> conversion between the FFI and Haskell representations will need to know
> that platform-dependent meaning so that it can do a meaningful conversion.

Wouldn't it be safer, and more portable, to use either :

call ctime, and get a string you can parse
call localtime, get back a struct tm which has int members you can work with.
Jason Dusek | 28 Mar 16:49 2013
Picon

Re: The numeric c types are (effectively) integral, too.

2013/3/28 David Virebayre <dav.vire+haskell <at> gmail.com>:
> 2013/3/28 Jason Dusek <jason.dusek <at> gmail.com>
>> One way to think of it is, CTime is time and should follow
>> the rules of the time. Another way is, CTime is a C type and
>> should follow the rules of C types.  The latter perspective
>> seems more appropriate for Foreign.C.* (we are likely to seek
>> out some other module for modelling time).
>
> I agree that the latter perspective seems more appropriate,
> however, according to Wikipedia :
>
> ISO C defines time_t as an arithmetic type, but does not
> specify any particular type, range, resolution, or encoding
> for it. Also unspecified are the meanings of arithmetic
> operations applied to time values.
>
> So, even if, in C, you may be able to apply arithmetic
> operations to a time_t, you can't be sure it makes sense, so
> you shouldn't normally do it. Why then, make it easier in
> Foreign.C to do something meaningless ? That's just begging to
> shoot yourself in the foot.

Working with C will always involve a lot of easy ways to shoot
off a foot or two. Why introduce ob/abstractions that can't
really move the needle, since C is so basically unsafe?

--
Jason Dusek
pgp // solidsnack // C1EBC57DC55144F35460C8DF1FD4C6C1FED18A2B
Brandon Allbery | 28 Mar 14:43 2013
Picon

Re: The numeric c types are (effectively) integral, too.

On Thu, Mar 28, 2013 at 6:32 AM, Jason Dusek <jason.dusek <at> gmail.com> wrote:
One way to think of it is, CTime is time and should follow the
rules of the time. Another way is, CTime is a C type and should
follow the rules of C types.  The latter perspective seems more
appropriate for Foreign.C.* (we are likely to seek out some
other module for modelling time).

Phrasing this perhaps more clearly: the point of the FFI types is to reflect foreign types. This may well include doing things which are legal in the foreign type but not necessarily sensible for the conceptual type --- and that may even be necessary in order to, say, convert that foreign type to something more appropriate for Haskell.

It ain't pretty; but it's the FFI, it's not going to be pretty. Or well behaved (just in case an interface that requires us to expose unsafePerformIO didn't make that clear...).

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b <at> gmail.com                                  ballbery <at> sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Henning Thielemann | 28 Mar 21:49 2013
Picon

Re: The numeric c types are (effectively) integral, too.


On Thu, 28 Mar 2013, Brandon Allbery wrote:

> On Thu, Mar 28, 2013 at 6:32 AM, Jason Dusek <jason.dusek <at> gmail.com> wrote:
>       One way to think of it is, CTime is time and should follow the
>       rules of the time. Another way is, CTime is a C type and should
>       follow the rules of C types.  The latter perspective seems more
>       appropriate for Foreign.C.* (we are likely to seek out some
>       other module for modelling time).
> 
> 
> Phrasing this perhaps more clearly: the point of the FFI types is to reflect foreign types.

If CTime is only for interfacing with C, then there should not be any 
arithmetic or bit manipulation class instances of it, only some conversion 
functions between CTime and Haskell time representations.
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Brandon Allbery | 28 Mar 21:53 2013
Picon

Re: The numeric c types are (effectively) integral, too.

On Thu, Mar 28, 2013 at 4:49 PM, Henning Thielemann <lemming <at> henning-thielemann.de> wrote:
On Thu, 28 Mar 2013, Brandon Allbery wrote:
On Thu, Mar 28, 2013 at 6:32 AM, Jason Dusek <jason.dusek <at> gmail.com> wrote:
      One way to think of it is, CTime is time and should follow the
      rules of the time. Another way is, CTime is a C type and should
      follow the rules of C types.  The latter perspective seems more
      appropriate for Foreign.C.* (we are likely to seek out some
      other module for modelling time).

Phrasing this perhaps more clearly: the point of the FFI types is to reflect foreign types.

If CTime is only for interfacing with C, then there should not be any arithmetic or bit manipulation class instances of it, only some conversion functions between CTime and Haskell time representations.

...and implementing those should be as painful as possible?

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b <at> gmail.com                                  ballbery <at> sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Henning Thielemann | 28 Mar 22:11 2013
Picon

Re: The numeric c types are (effectively) integral, too.


On Thu, 28 Mar 2013, Brandon Allbery wrote:

> If CTime is only for interfacing with C, then there should not be any arithmetic or bit manipulation
> class instances of it, only some conversion functions between CTime and Haskell time representations.
> 
> 
> ...and implementing those should be as painful as possible?

Implementing these conversion functions means unpacking data from the 
CTime constructor and convert it to Haskell time representations or vice 
versa. I don't think it is possible to write conversion functions using 
Num and Bits that work on all architectures. If there is functionality 
that can be used on multiple architectures this should be provided as 
helper functions.
Brandon Allbery | 28 Mar 22:20 2013
Picon

Re: The numeric c types are (effectively) integral, too.

On Thu, Mar 28, 2013 at 5:11 PM, Henning Thielemann <lemming <at> henning-thielemann.de> wrote:
On Thu, 28 Mar 2013, Brandon Allbery wrote:
If CTime is only for interfacing with C, then there should not be any arithmetic or bit manipulation
class instances of it, only some conversion functions between CTime and Haskell time representations.

...and implementing those should be as painful as possible?

Implementing these conversion functions means unpacking data from the CTime constructor and convert it to Haskell time representations or vice versa. I don't think it is possible to write conversion functions using Num and Bits that work on all architectures. If there is functionality that can be used on multiple architectures this should be provided as helper functions.

Can't be done on all architectures, therefore we should ensure it can't be done at all. Which means CTime can never actually be used from Haskell, not even by converting it to a Haskell-friendly representation, but only as an opaque blob; that's really helpful when interfacing to e.g. POSIX functions.

--
brandon s allbery kf8nh                               sine nomine associates
allbery.b <at> gmail.com                                  ballbery <at> sinenomine.net
unix, openafs, kerberos, infrastructure, xmonad        http://sinenomine.net
_______________________________________________
Libraries mailing list
Libraries <at> haskell.org
http://www.haskell.org/mailman/listinfo/libraries
Jeff Shaw | 29 Mar 01:30 2013
Picon

Re: The numeric c types are (effectively) integral, too.

On 3/28/2013 5:11 PM, Henning Thielemann wrote:
>
> On Thu, 28 Mar 2013, Brandon Allbery wrote:
>
>> If CTime is only for interfacing with C, then there should not be any 
>> arithmetic or bit manipulation
>> class instances of it, only some conversion functions between CTime 
>> and Haskell time representations.
>>
>>
>> ...and implementing those should be as painful as possible?
>
> Implementing these conversion functions means unpacking data from the 
> CTime constructor and convert it to Haskell time representations or 
> vice versa. I don't think it is possible to write conversion functions 
> using Num and Bits that work on all architectures. If there is 
> functionality that can be used on multiple architectures this should 
> be provided as helper functions.
>
> _______________________________________________
> Libraries mailing list
> Libraries <at> haskell.org
> http://www.haskell.org/mailman/listinfo/libraries
Please tell us which Haskell compiler targets a platform with a CTime 
representation that supports Num, but wouldn't support Integral, Bits, 
or Enum. Or heck, what Haskell target platform's time_t isn't an integer?

Jeff
Jeff Shaw | 29 Mar 22:40 2013
Picon

Re: The numeric c types are (effectively) integral, too.

I've formed my proposal in a more formal venue.

http://hackage.haskell.org/trac/ghc/ticket/7801

Jeff

Gmane