Skip to content

Instantly share code, notes, and snippets.

Forked from renanreismartins/adam.scala
Last active February 18, 2018 22:05
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
What would you like to do?
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](, 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