Skip to content

Instantly share code, notes, and snippets.

@bergmark
Forked from renanreismartins/adam.scala
Last active February 18, 2018 22:05
Show Gist options
  • Save bergmark/093b3b7e1758a7d7fc15461e9a767fd3 to your computer and use it in GitHub Desktop.
Save bergmark/093b3b7e1758a7d7fc15461e9a767fd3 to your computer and use it in GitHub Desktop.
sealed trait State
case class WithOffer(offer: Offer) extends State
object WithOffer {
implicit val hasOffer: HasOffer[WithOffer] = _.offer
}
case class WithoutOffer() extends State
case class WithPartner(partnerName: String) extends State
case class WithOfferAndPartner(offer: Offer, partnerName: String) extends State
object WithOfferAndPartner {
implicit val hasOffer: HasOffer[WithOfferAndPartner] = _.offer
}
trait HasOffer[S] {
def offer(s: S): Offer
}
object HasOffer {
def getOffer[S: HasOffer](s: S): Offer = implicitly[HasOffer[S]].offer(s)
}
case class Offer(id: Int)
case class Merchant[S <: State](name: String, state: S)
object Merchant {
def withoutOffer(name: String): Merchant[WithoutOffer] =
Merchant[WithoutOffer](name, WithoutOffer())
def withOffer(name: String, offer: Offer): Merchant[WithOffer] =
addOffer(withoutOffer(name), offer)
def addOffer(merchant: Merchant[WithoutOffer], offer: Offer): Merchant[WithOffer] =
Merchant[WithOffer](merchant.name, WithOffer(offer))
import scala.language.implicitConversions
implicit def hasOffer[S <: State: HasOffer]: HasOffer[Merchant[S]] =
(m: Merchant[S]) => HasOffer.getOffer(m.state)
}
object Main extends App {
def printOffer(merchant: Merchant[WithOffer]): Unit = {
println("offer: %s", HasOffer.getOffer(merchant))
}
printOffer(Merchant.withOffer("renan", Offer(1)))
println(HasOffer.getOffer(Merchant.withOffer("renan", Offer(1))))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment