CLOVIS
06/15/2020, 1:18 PMinterface Event {
val start: ...
val end: ...
val canSubscribe: Boolean
suspend fun subscribe()
}
But that's a lot of boilerplate per feature, and since I want to learn Arrow, I'm thinking there must be a better way.
What do you think of:
interface Event {
val start: ...
val end: ...
fun subsribe(): Either<UnsupportedOperationException, IO<Unit>>
}pakoito
06/16/2020, 12:27 AMpakoito
06/16/2020, 12:28 AMpakoito
06/16/2020, 12:28 AMpakoito
06/16/2020, 12:34 AMpakoito
06/16/2020, 12:35 AMpakoito
06/16/2020, 12:36 AMsuspend fun subscribe(start, end): Either<UnsupportedOperationException, Unit>
subsume all functionality you need? maybe it needs one or two additional parametersCLOVIS
06/16/2020, 8:18 AMpakoito
06/16/2020, 9:40 AMpakoito
06/16/2020, 9:40 AMpakoito
06/16/2020, 9:41 AMpakoito
06/16/2020, 9:42 AMCLOVIS
06/16/2020, 9:51 AMCLOVIS
06/16/2020, 9:51 AMpakoito
06/16/2020, 3:13 PMpakoito
06/16/2020, 3:13 PMpakoito
06/16/2020, 3:13 PMpakoito
06/16/2020, 3:13 PMpakoito
06/16/2020, 3:14 PMclass Parent {
open fun bla() {
doThing()
}
}
class Child1 {
override fun bla() {
super.bla()
someThing()
}
}
class Child2 {
override fun bla() {
super.bla()
otherThing()
}
}pakoito
06/16/2020, 3:14 PMpakoito
06/16/2020, 3:16 PMfun bla(f: () -> Unit) {
doThing()
f()
}
...
when (val action = getAction()) {
is Action1 -> bla { action.someThing() }
is Action2 -> bla { action.otherThing() }
}pakoito
06/16/2020, 3:17 PMbla can be definedpakoito
06/16/2020, 3:18 PMsuspend fun <A: Serializable, B> bla(before: () -> A, after: (A) -> B): B {
val thing = before()
serialize(thing)
return after(thing)
}pakoito
06/16/2020, 3:19 PMwhen (val action = getAction()) {
is Action1 -> bla(before = { processAction(action) }, after = { action.someThing(it) })
is Action2 -> bla(before = { action.someField }, after = { action.otherThing(it) })
}pakoito
06/16/2020, 3:20 PMhandleError on top of this way of writing codepakoito
06/16/2020, 3:21 PMCLOVIS
06/16/2020, 8:53 PMpakoito
06/16/2020, 10:25 PMpakoito
06/16/2020, 10:25 PMpakoito
06/16/2020, 10:26 PMpakoito
06/16/2020, 10:26 PMpakoito
06/16/2020, 10:26 PMpakoito
06/16/2020, 10:26 PMpakoito
06/16/2020, 10:26 PMpakoito
06/16/2020, 10:27 PMpakoito
06/16/2020, 10:27 PMpakoito
06/16/2020, 10:27 PMpakoito
06/16/2020, 10:27 PMpakoito
06/16/2020, 10:28 PMpakoito
06/16/2020, 10:28 PMpakoito
06/16/2020, 10:28 PMpakoito
06/16/2020, 10:29 PMpakoito
06/16/2020, 10:30 PMpakoito
06/16/2020, 10:31 PMpakoito
06/16/2020, 10:32 PMpakoito
06/16/2020, 10:32 PMpakoito
06/16/2020, 10:33 PMpakoito
06/16/2020, 10:33 PMpakoito
06/16/2020, 10:34 PMCLOVIS
06/17/2020, 8:20 AMinterface Event
interface Priority
interface GoogleMeetConference
interface Notifications
class GoogleEvent : Event, GoogleMeetConference, Notifications
class NextCloudEvent : Event, Priority, Notifications
class AppleEvent : Event
I think it's good because it allows to write a when to know which functionalities are supported by a particular object, to eg. hide the other options when it's displayed; but it sounds to me like a lot of code, what do you think?pakoito
06/17/2020, 11:04 AMpakoito
06/17/2020, 11:04 AMpakoito
06/17/2020, 11:07 AMEvents can be synced with multiple providers, eg. Google Calendar, NextCloud and Apple Calendar. Google doesn’t support setting a priority, but NextCloud does. Google allows you to create a Google Meet conference, but both others don’t. Google and NextCloud let’s you set notifications, but Apple doesn’t [I’m sure Apple does as well, that’s just for the example].that’s fine, each can do its own thing. What’s telling them what to set? can you make a single mega data class with all this info, then delegate to each implementation to set according to its own capabilities
pakoito
06/17/2020, 11:08 AMpakoito
06/17/2020, 11:13 AMdata class Event(val p: Priority, val c: ConferenceRoom, val n: Notification)
interface EventVisitor<T> {
suspend fun visit(e: Event): T
}
object GoogleEventSave: EventVisitor<Unit> {
suspend fun visit(e: Event): Unit {
GoogleAPI.newEvent().setConference(e.c).submit()
}
}
object NextCloudSave: EventVisitor<Unit> {
suspend fun visit(e: Event): Unit {
NextCloud().makeEvent().setConference(e.c).setPriority(e.p).save()
}
}pakoito
06/17/2020, 11:14 AMpakoito
06/17/2020, 11:16 AMsuspend fun Event.save(v: EventVisitor<Unit>): Unit = v.visit(this)pakoito
06/17/2020, 11:16 AMmyEvent.save(GoogleEventSave)pakoito
06/17/2020, 11:18 AMpakoito
06/17/2020, 11:22 AMpakoito
06/17/2020, 11:25 AM@extension interface SaveEvent<F, T>: EventVisitor<Unit> {
suspend fun visit(e: Event): Unit
suspend fun Event.save(): Unit = visit(this)
}
object GoogleEventSave: SaveEvent<ForGoogle> {
suspend fun visit(e: Event): Unit {
GoogleAPI.newEvent().setConference(e.c).submit()
}
}
object NextCloudSave: SaveEvent<ForNextCloud> {
suspend fun visit(e: Event): Unit {
NextCloud().makeEvent().setConference(e.c).setPriority(e.p).save()
}
}
myEvent.save() // SaveEvent is resolved statically on the method where this line is. Otherwise the method needs to be parametrized for FCLOVIS
06/17/2020, 7:49 PMCLOVIS
06/17/2020, 9:05 PMCLOVIS
06/17/2020, 9:12 PMCLOVIS
06/17/2020, 9:21 PMobject GooglePriorityProvider: Priority<ForGoogle> {
private val priorities: MutableMap<Event, Int>
var Event.priority by priorities[this]
}
But then, the GoogleEventSave object should know about it to be able to save that information as well?
Is there such a thing as implementing a typeclass as a class and not an object, so it can have state linked to the original object? Sorry if this doesn't make sense, typeclasses are not fully clear to my mind, at this point.