<@U5F0TT0UX> Have you thought about using F-bounde...
# mathematics
b
@altavir Have you thought about using F-bounded quantification in your algebra? It’s a nice way to get concrete types out of an abstract structure while only defining behavior once on the most generic type. For example, try to define an extension function
buffer.min()
over an arbitrary buffer whose elements are subtypes of
Comparable
where
min()
returns a specific type (i.e. not a
Comparable
)? Can you implement it using a single function?
a
I do not know what F-quantification is (not a CS guy, remember?), but it works exactly like this now. In order to get some new function you just define an extension on the Algebra of the type.
For comaparable you can just write
fun <T> Buffer<out Comparable<T>>.min()
or something like that and it will work for all buffers (thanks to static dispatch). For algebra you can define things like folding. I am working on stream processing of those now.
You can see an example here: https://github.com/altavir/kmath/blob/dev/kmath-core/src/commonMain/kotlin/scientifik/kmath/operations/Algebra.kt#L37. I would move to extensions, but I need KEEP-176 for that.
Probably should move it anyway and convert to
Space<T>.sum(iterable : Iterable<T>)
b
But you get an
out Comparable<T>
back, right? Suppose I have a new numeric type
Float16
that implements
Comparable
and I want
Float16
back
a
It requires a bit more complicated generic. A moment please
fun<T: Comparable<T>> Buffer<T>.max(): T? = asSequence().max()
It does not require Kmath. You need it when you actually want some operations
b
Right,
<T: Comparable<T>>
simplifies a lot of boilerplate for specializing to subtypes
a
It does not solve self-type problem. Element types are complicated because of recursive generics
I mean in Kmath.
b
I’m not sure about the performance issues of checking recursive types when you have a long chain of subtypes
But it helps to avoid some boilerplate
a
It is completely free. Those generics exist only in compile-time
b
Type checking is not free, but the cost is incurred at compile time
a
It is almost free. Compared to things like annotation processing it is almost zero. Of course if you are not talking about Scala
b
Even Java’s type system is Turing Complete, you can send the checker into an infinite loop https://bugs.eclipse.org/bugs/show_bug.cgi?id=543480
Anyhow, this is the issue we run into with shape checking tensor algebra for long chains
I don’t think it would be expensive for type checking a small set of types, but if you have type-level integer literals, it can get expensive
a
No, it is not the same. Generics do not generate new classes. What you want is a full-fledged higher order type system, which in turn requires new classes for each singleton-type.