Description
Currently, we have:
- A ton of extension interfaces: CheckedDatastore, ScrubbedDatastore, Batching, etc...
- A ton of wrappers: Delayed, Mount, Sync, Autobatch, etc...
And unfortunately, every wrapper needs to implement and forward every extension interface to the underlying datastore. It's kind of a nightmare.
According to @bigs, however,
Typeclasses and modules compose pretty cleanly stuck_out_tongue! Monad transformers exhibit that kind of extensionality pretty well!
I'm not sure about languages like Haskell but I'm pretty sure this can't be done in most languages. However, it's worth discussing as it would be great to have a better system.
Basically, what I want is (pseudo-rust):
trait Datastore { ... }
trait GCDatastore: Datastore { ... }
struct MyDs {
...
}
impl Datastore for MyDs { ... }
struct Delayed<D: Datastore> {
inner: D,
delay: Duration,
}
impl<D: Datastore> Datastore for Delayed<D> {}
// Can't express this:
forall<X> auto impl X for Delayed<D> where D: X via self.inner;
// That is, auto implement all traits implemented by D on Delayed<D> by proxying to self.inner.
This kind of behavior is usually achieved via the Deref
trait. In rust, if a type X
implements Deref<Target=SomeOtherType>
and someone calls some_x.foo()
, the compiler will first try to lookup foo
on X
, then on SomeOtherType
, recursively (if SomeOtherType
also implements Deref
). However, this doesn't mean that the type X
actually implements any of the traits implemented by SomeOtherType
.
Thoughts?