On Wed, Nov 12, 2014 at 12:18 PM, Herbert Valerio Riedel wrote:
Btw, a somewhat related approach I tuned heavily (but relies on 'Bits'
rather than 'Bounded')

http://hackage.haskell.org/package/int-cast-0.1.1.0/docs/Data-IntCast.html#v:intCastMaybe

Nice. I had admittedly forgotten about int-cast when I went looking for this kind of thing.

I'm a worried about the implementation requiring all those RULEs defined
in order to get GHC to optimize it away. That looks like the wrong way
to approach this, as by that you get something of an O(n^2) complexity
when you need to add new integral types to the RULE set to account for
all the potential direct conversion-paths between each pair.

That's a valid concern.

Just so you know, this is nearly the same set of RULEs defined for fromIntegral. The fromIntegral RULEs just happen to be spread around different modules: Foreign.C.Types, GHC.Float, GHC.Int, GHC.Real, and GHC.Word. toBoundedIntegral has 101 vs. fromIntegral's 88 RULEs. The extra RULEs account for some 32-/64-bit special cases (with some alternatives behind #if's) and a few other cases that are not accounted for by the fromIntegral RULEs. For adding a numerical type to base, it effectively adds the same burden that fromIntegral requires in terms of RULEs.

I'd love to be able to depend on the fromIntegral RULEs instead of adding toBoundedIntegral RULEs, but I found cases where the fromIntegral RULEs were not firing. So I thought I would make GHC's job easier by including all of the RULEs. If there's a better way, I'm all for it.

Moreover, you limit yourself to 'Bounded' types (which is why I resorted
`Bits` rather than 'Bounded' for 'intCastMaybe' after noticing that I
couldn't convert from (half)unbounded 'Integer' or 'Natural' to/from
bounded types).

I'm not sure how the function is “limited” by using Bounded. Aren't they just different constraints? If your type doesn't have a Bits instance but does have a Bounded, then you would use the function that required Bounded. How often this happens in practice, I don't know.

Anyway, I don't see a reason why we couldn't have both toBoundedIntegral and intCaseMaybe. Or, if you prefer intCaseMaybe, let's use that instead. I'm not strongly tied to toBoundedIntegral, but it would be nice to see something in base because more people will see it.

So I'm on the fence about 'toBoundedIntegral', as for one I want such a
facility for conversion, but OTOH, I'm not happy with the limitations
'toBoundedIntegral' exhibits. I'd like to see a more general solution.

Just to be clear, I understand one limitation you've presented: the RULEs. You mentioned limiting to Bounded, but I'm not clear how that's a limitation compared to using Bits, as you do.

What do you mean by a more general solution? IMHO, this is simply a “better” fromIntegral, and fromIntegral is used a lot for bounded types. I don't see how having toBoundedIntegral or intCaseMaybe precludes or diminishes other developments, esp. ones that deal with more type information. These functions are useful as they are now for many types.

PS: While working on the `int-cast` package (as well as experimenting
with type-level int literal-indexed integers[1]), I couldn't help but
wonder if we benefit from some GHC-provided facility for reflecting
integral boundary information at the type-level. One of the things I was
wishing for was for Haskell to support arbitrary statically-typed
(contiguous) sub-ranges of 'Integer' where GHC could then pick the most
efficient underlying type.


 [1]: https://github.com/hvr/fixed-width-integers/blob/master/Data/Int/Fixed.hs

Also nice.

Regards,
Sean