On Sat, Sep 8, 2018 at 7:53 PM, Jonathan Amsterdam
<jbamster...@gmail.com> wrote:
>>  When is it important to not just express what operations are
>> required for a type, but also to try to rule out some types?
>
>
> I think the short answer is: numeric code. That's when one thinks about
> which types make sense for an algorithm, not just which operations.
>
> I'm not exactly sure why. It could be because Go doesn't support operator
> overloading. In C++ with concepts, maybe the concept for writing some
> generic math function wants operator+ and operator/, and no one cares that
> that may result in nonsense for some implementations of those operators.
>
>  In Go 1, we write numeric code with specific types: float64 and not int64,
> for instance. Go  insists on conversions between numeric types to keep us
> out of trouble: you can't call func Average(a, b float64) on ints without
> explicitly converting them. It seems natural to want to keep that precision
> and safety, but generalize it.
>
> In Go 1, if we wanted to write a numeric algorithm that worked on, say, two
> slices of floating-point numbers, we'd give it the signature func(x, y
> []float64). If later we wanted to support float32, we'd have to copy the
> code, or make the caller do an expensive conversion. The same problem would
> happen if the caller defined their own floating-point type (e.g. type
> MyFloat float64).
>
> I think I should be able to say, simply and clearly, that the slice element
> can be any type whose underlying type is float32 or float64. Furthermore, I
> don't want to specify the exact operations my implementation currently uses.
> I may want to change the code to use "-" instead of "+" later, for reasons
> of clarity or numerical stability. I shouldn't have to update the contract
> for that.
>
> contract(t T) { t = 0.0 } might seem to restrict to the types I want, but it
> doesn't; you can assign 0.0 to an integer type.
>
> contract(t T) { t = 0.5 } is wrong too. It includes complex types.
>
> contract(t T) { float64(t) } also works for ints, so no good.
>
> I believe the answer is
>
>    contract(t T) { t = 0.5; float64(t) }
>
> but I'm not positive about that. Certainly, very few people who read that
> will immediately understand that T is a type whose underlying type is a
> float.
>
> (And I haven't done the second part, where I add all the valid operators for
> floats.)
>
> Earlier you wrote
>
>> [T]o me it always seems quite clear which type arguments a contract allows
> and excludes.  It's exactly the set of types that type check
> successfully.  It's true that sometimes this can be a surprising type,
> but to me that seems just like the fact that it can be surprising
> which types implement an interface.
>
> I think this example, and the other ones given in this thread, demonstrate
> that this is not "just like" the surprise of which types implement an
> interface. It's more like solving a puzzle, as someone (Axel?) has said.

It is like solving a puzzle because you are trying to figure out how
to exclude some types.  Why are you doing that?  Why not just describe
the types you accept, and not worry about other types?  Just as we do
for interface types?

I don't yet find your Average example to be convincing.  Clearly if
Average is going to take values of type T and return a value of type
T, then if called on integers it is going to be a rounded value.  That
is inherent in the description.  I don't see this as analogous to the
fact that we require explicit type conversions between different
numeric types.

Ian

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to