Saying having less information about the data makes for easier coding is almost always not true.
You say that, but you probably don't actually do it. If it truly could "be anything" then you would not be able to do anything to it. This is the nature of polymorphism.
So instead, your algorithm constrains the polymorphism based on what you need. If you make use of the properties {small, bit-shiftable, sized, bounded, copy-safe} then you must prove (exactly and only) that whatever the generic variable gets instantiated to satisfies {small, bit-shiftable, sized, bounded, copy-safe}.
Indeed, this is part of how such a system prevents bugs---it forces you to express exactly how much information about the types involved is needed. You can thus reflect better on the kinds of contracts/laws things must uphold and are prevented from accidentally making use of a property of your concrete type which you do not demarcate.
In a truly expressive language you might write
foo : forall id n .
(Bits id, Size id = n, n <= 1024)
=> id -> {Copy id} id
to indicate all of those properties needed (bounded being subsumed by constraining the size)Today, you can get promises very similar to the above by using a language like Cryptol[0].
The closest I've gotten to that has been to create a single-member wrapper struct. Go provides a little bit of sugar for that, but it results in a decent amount of boilerplate and explicit wrapping/unwrapping.
type Foo struct {
pkg.Bar
}
func UseIt(b pkg.Bar) error {
return otherFunc(Foo{b})
}
I think that's actually one of the places Go works really well. It sounds like you want something like C#'s extension methods, which I don't think are a good thing (I used them a bunch in a past job). The problem with them is that it means your code can spontaneously and mysteriously break if you move it somewhere else that isn't including the project that has the extensions. Extensions seemed nice, but they really only made the code a tiny bit cleaner, and the added complexity did not really make up for it, in my opinion.Another thing is that assertions can only check primitive type. To check if a function pointer or object respects an interface you need to add an extra wrapper around it to check all its return values (and this is so annoying to do by hand that noone bothers to do it)