Closed rssh closed 1 year ago
Uhm not sure what you mean, you can just use IterableOnce
to accept any collection and obtain its Iterator
Or you may use the IsIterableOnce
typeclass to be even more generic.
Sorry, I can't understand your statement about IterableOnce.
The criteria are simple: is it possible to implement trait IteratorAccess
for generic C
over the current standard library?
As I know, we have no something like IsIterableOnce
typeclass in the standard library. Can you be more specific?
oops, found https://www.scala-lang.org/api/2.13.5/scala/collection/generic/IsIterableOnce.html
But it's. defined over C[A]
, not overC[_]
.
Therefore it is still impossible to write a generic algorithm knowing only C[_]
without an instance of C[A].
Ham no, it is defined over any C
.
Maybe I am the one who is not understanding you, what kind of meta-problem do you want to solve? And how do you think your proposed typeclass would solve it.
As I see in code:
trait IsIterableOnce[Repr] {
type A
....
}
i.e. Repr
. here is C[A]
, because you know A
. (When it over C[_]
we don't know A, it will supplied later as type parameter)
I need a typeclass over a class constructor.
The most simple example: Implement IteratorAccess[C[_] <: ???]
in generic way.
Another simple example (MB more understandable]:
ForEachRunner[C[_] (type-constraints-should-be-here)] {
def run[A](a:C[A])(fu: A=>Unit): Unit
}
I can't find a way to build ForEachRunner[List]
. from a List
constructor.
If we will add to IterableFactory
method retrieveIterator
and add a given instance of IterableFactory
in a List
scope, this will become possible:
ForEachRunner[C[_]:IterableFactory] {
def run[A](a:C[A])(fu: A=>Unit): Unit = {
val it = summon[IterableFactory[C]].retrieveIterator(ca)
......
}
}
So you want an Iterator
of a class rather than a value.
How would that even work? What values would it yield?
Signature should be
trait IterableFactory[C[_]] {
....
def retrieveIterator[A](c:C[A]):Iterator[A]
}
Get collection with a given type as parameter and return it's iterator.
I.e. the main value, is that we can use retrieveIterator
in a situation when we have no C[A] in supplied of inferred type parameters but have only C[_]
. (or. CC[_]
is use current standard library conventions).
Note, that IterableFactory
already have newBuilder
method which works in a similar way.
What other methods would have that typeclass?
And are you sure IsIterableOnce
and IterableOnceOps
don't already support that?
Again, instead of repeating what you want, why not show an actual real problem you need to solve and show how that typeclass of yours would solve it.
Is an example with ForEachRunner
is not sufficient for you?
I.e. I mean, if you will start trying to implement given IteratorAccess[C[_]]
or ForEachRunner[C[_]]
then you will see the problematic.
No, is not clear at all.
What is ForEachRunner
a class, a method?
If a class, why it has to be a class? Who would instantiate it, when? How? Who would use it? How would use it?
What is the implementation of run
?
What are those extra type constraints?
O'key, let's try to specify all details.
Let we have definition:
trait ForEachRunner[C[_]]. {
///. run function over all elements of C
def run[A](ca:C[A])(f: A=>Unit): Unit
}
Now I want to implement ForEachRunner for the set of collections.
for example, here is an implementation for List
class ListForEachRunner extends ForEachRunner[List] {
def run[A](ca:C[A])(f: A=>Unit): Unit = {
val it = ca.iterator
while(it.hasNext) {
f(it.next)
}
}
}
(of course, foreach
is a simplification; in reality, this can be any generic algorithm. [C++ STL is built in such a way] )
I want to write something other than a definition for each concrete collection. But for this, I need to retrieve an iterator in a generic way, knowing only the collection constructor CC[_].
Usage:
val algo = summon[ForEachRunner[List]].
algo.run(List(1,2,3))(i => println(i))
algo.run(List("1","2","3"))(i => println(i))
Is it important for it to be a type? Rather than just add the extension method.
Anyways, both versions are implementable using IsIterableOnce
quite easily; you just need to ask for it on the run
method. Or even, no need the indirection, just use IterableOnce
and subtyping.
How ?
To use IsIterableOnce
I. should know the element type (or pass an implicit parameter to run)
I.e. we have a quite clear task: implement ForEachRunner
for generic collection type without knowing an element type and without passing an additional parameter to run
.
I.e. we can pass something to the constructor of our IterableOnceForEachRunner
implementation, but not to the run
method.
run
can't accept an implicit IsIterableOnce
[C[x] <: IterableOnce[x]]
and that is all, you don't need any indirection.run
. I.e. we want to incapsulate all knowledge about carriers in our typeclasses.retrieveIterator
is not needed). Great, thanks!What-s left: an implicit instance of IterableFactory into the companion object of each collection type
.
Example: let we have algorithm. Empty:
trait Empty[C[_]] {
def run[A](): C[A]
}
And again, we can build this for list
class ListEmpty extends Empty[List] {
def run[A](): List[A] = List()
}
In generic case ... only one implicit is BuildFrom and it's dependent from element type.... :
class IterableEmpty[CC[x]](using buildFrom: BuildFrom[CC[?],?,CC[?]) extends Empty[List] {
def run[A](): CC[A] =
... naive buildFrom.newBuilder will give us incorrect type
}
//. better be discussed separately in another thread.
@rssh you may use IterableFactory
: https://www.scala-lang.org/api/current/scala/collection/IterableFactory.html
Sadly, the values are not implicit, only the Factory
ones; I really find the whole Factory
hierarchy confusing.
Anyways, if you are okay with passing the companion object rather than the type, you can do something like this: https://scastie.scala-lang.org/zQeS83ygQDaupa0dH7nncw
@BalmungSan thanks. yes Finally, I retrieved the companion object from type by macros, but this looks like cheating. // https://github.com/rssh/dotty-cps-async/blob/master/shared/src/main/scala/cps/macros/misc/CollectionHelper.scala
(and given instance based only on type in a situation close to described: https://github.com/rssh/dotty-cps-async/blob/9032c425b5dee2eef6682ca5f42cc61a59d84761/shared/src/main/scala/cps/monads/IterableCpsMonad.scala#L55 )
Still plan to provide a minimal changeset to make a 'normal' solution possible.
Currently, it is impossible to construct a collection iterator knowing only the type of a type constructor. Something like
Therefore it is hard to write generic algorithms over collections.
Proposal:
discarded add to IterableFactory[CC[_]] method retrieveIteratorA:Iterator[A]-- ^H^H^H. not needed
add an implicit instance of IterableFactory into the companion object of each collection type