-
Notifications
You must be signed in to change notification settings - Fork 10
Conversation
|
||
def merge( | ||
v: Event[A] | ||
): Event[A] = { // if Event[ A]: covariant type A occurs in contravariant position |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not remove variance, the way it is done is by providing events of a supertype of A, so the type signature of merge must be:
def merge[AA >: A](v: Event[AA]): Event[AA]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, thanks
): Event[A] = { // if Event[ A]: covariant type A occurs in contravariant position | ||
|
||
val winner: IO[Nothing, Either[(Time, Reactive[A]), (Time, Reactive[A])]] = | ||
self.value.force.map(Left(_)).race(v.value.force.map(Right(_))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is no need to put them inside an Either, the resulting IO will have the winner, so self.value.force race v.value.force
will be enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True - at one moment I had the idea I needed the loser too, but that is not the case.
Future((t, Reactive(r.head, r.tail))) | ||
}) | ||
|
||
Event(unsafeRun(io)) // That is not good |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed it is not good, we should NEVER use the RTS
trait on our code, or we will be limiting our implementation to the jvm and it is clear that we are leaking side effects. this is why I said we can experiment with type Future[ A] = IO[Void, (Time, A)]
so that in this case it is a simple race operation:
def merge[AA >: A](v: Event[AA]): Event[AA] = Event(self.value race v.value)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wow :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed, once we are in IO, we have to stay in the IO, so I can't think of another way to do this at the moment.
implicit def monoidEvent[E, A]: Monoid[Event[A]] = | ||
new Monoid[Event[A]] { | ||
|
||
override def zero: Event[A] = Event(Future.Never) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we make Future = IO, then this is a good one because we would need to make an IO which never resolves and always loses race operations, maybe, for now, an IO with a fiber that is always blocked? we can analyze efficiency later
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i might be completely off here, but merge
seems to be just a monoidal append
in the paper, so should merge =
where
is the Future's
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@FrancoAra IO provides IO.never - Returns a action that will never produce anything.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hienqnguyen I guess we should do the racing in the Future's
and end up with what you say.
import scalaz.{ Applicative, Functor, Monad, Monoid } | ||
|
||
case class Future[ A](time: () => Time, force: () => A) { | ||
object Types { | ||
type Infallible[A] = IO[Nothing, A] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this be type Infallible[ A] = IO[Void, A]
? to ensure that this does not get flat mapped with an IO which does fail? or maybe I'm wrong
case (t1, a1) => | ||
other.force.map { | ||
case (t2, a2) => if (t1 <= t2) (t1, a1) else (t2, a2) | ||
} //There should be IO.ap, is there? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this has the same dilemma as the events... if we make Future[A] = IO[Void, (Time, A)] then I would say we shouldn't implement this monoid for now
Future(force.flatMap { | ||
case (t, a) => | ||
f.force | ||
.map { case (t2, f) => (t2.max(t), f(a)) } // There should be IO.ap, is there? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes we could use IO ap instead of flatMap, I am not sure what are the difference in the semantics of the IO ap and flatMap, they are the same if ap is defined in terms of flatMap
Future =IO[Void, (Time, A)