Skip to content

Instantly share code, notes, and snippets.

@fanf
Last active August 24, 2016 12:56
Show Gist options
  • Save fanf/6c45cb0cac28e6bd75c4204f59245a9a to your computer and use it in GitHub Desktop.
Save fanf/6c45cb0cac28e6bd75c4204f59245a9a to your computer and use it in GitHub Desktop.
/*
* Follow up of https://gist.github.com/fanf/845273a15377347a04375d51a0139b78
* trying to use the new onionT1/onionT2/onionT3 from cats 0/6
*/
object Test1 {
type Maybe[A] = Xor[String, A]
final case class Query(value: String)
final case class Result(value: String)
sealed trait Backend { def search(q: Query): Maybe[List[Result]] }
/* final case object Backend1 extends Backend {
def search(q: Query) = Xor.right(List(Result("a"), Result("b")))
}
final case object Backend2 extends Backend {
def search(q: Query) = Xor.right(List(Result("c")))
}
final case object Backend3 extends Backend {
def search(q: Query) = Xor.left("This is a structured error message. Really. See: ponctuation.")
}
*/
sealed trait MayFail1[A]
final object MayFail1 {
final case class Parse(query: String) extends MayFail1[Maybe[Query]]
}
sealed trait PureProcess[A]
final object PureProcess {
final case object MultiBackends extends PureProcess[List[Backend]]
}
sealed trait MayFail2[A]
final case object MayFail2 {
final case class GetMulti(query: Query, backends: List[Backend]) extends MayFail2[Maybe[List[Result]]]
}
type P = MayFail1 :|: MayFail2 :|: PureProcess :|: NilDSL
val P = DSL.Make[P]
type O2 = Maybe :&: List :&: Bulb
def search3(input: String): OnionT[Free, P.Cop, O2, List[Result]] = {
for {
query <- MayFail1.Parse(input) .freek[P].onionT[O2]
b <- PureProcess.MultiBackends .freek[P].onion[O2]
res <- MayFail2.GetMulti(query, b) .freek[P].onionT1[O2] // does not compile :(
} yield {
res
}
}
val a3: Free[P.Cop, Maybe[List[Result]]] = search3("plop").value
@mandubian
Copy link

it's normal that it doesn't compile .onionT1 returns a OnionT[Free, P.Cop, Maybe :&: Bulb, List[Result]] but other lines return OnionT[Free, P.Cop, Maybe :&: List :&: Bulb, Result]... so for-comprehension is broken as types are not the same on all lines... normal :)

to me, your onion is type O2 = Maybe :&: Bulb and you must use .onion on 2nd/3rd line

@fanf
Copy link
Author

fanf commented Aug 24, 2016

I started with that, but the returned type is not OK, we get too many Maybe in the end:

  type O2 = Maybe :&: Bulb

  def search3(input: String): OnionT[Free, P.Cop, O2, Maybe[List[Result]]] = {
    for {
      query <- MayFail1.Parse(input)         .freek[P].onionT[O2]
      b     <- PureProcess.MultiBackends     .freek[P].onion[O2]
      res   <- MayFail2.GetMulti(query, b)   .freek[P].onion[O2]
    } yield {
      res
    }
  }

  val a3: Free[P.Cop, Maybe[Maybe[List[Result]]]] = search3("plop").value

@mandubian
Copy link

oh I had missed that GetMulti already contains the Maybe...
so 3rd line should be onionT

@fanf
Copy link
Author

fanf commented Aug 24, 2016

Still not working, I think I tested that option to. The error is:
could not find implicit value for parameter lifter2: freek.Lifter2.Aux[cats.data.Xor[String,List[com.normation.rudder.services.quicksearch.Test1.Result]],com.normation.rudder.services.quicksearch.Test1.O2,com.normation.rudder.services.quicksearch.Test1.Result]

@mandubian
Copy link

ok I see... it can't lift Maybe[List[Result]]] to Maybe :&: Bulb... there is nothing to do that...

For now, you can do:

import freek._
import cats.free.Free
import cats.data.Xor

import cats.instances.option._
import cats.instances.list._

/*
 * Follow up of https://gist.github.com/fanf/845273a15377347a04375d51a0139b78
 * trying to use the new onionT1/onionT2/onionT3 from cats 0/6
 */

 object Test1 {

  type Maybe[A] = Xor[String, A]

  final case class Query(value: String)
  final case class Result(value: String)
  sealed trait Backend { def search(q: Query): Maybe[List[Result]] }
/*  final case object Backend1 extends Backend {
    def search(q: Query) = Xor.right(List(Result("a"), Result("b")))
  }
  final case object Backend2 extends Backend {
    def search(q: Query) = Xor.right(List(Result("c")))
  }
  final case object Backend3 extends Backend {
    def search(q: Query) = Xor.left("This is a structured error message. Really. See: ponctuation.")
  }
*/
  sealed trait MayFail1[A]
  final object MayFail1 {
    final case class Parse(query: String) extends MayFail1[Maybe[Query]]
  }

  sealed trait PureProcess[A]
  final object PureProcess {
    final case object MultiBackends extends PureProcess[List[Backend]]
  }

  sealed trait MayFail2[A]
  final case object MayFail2 {
    final case class GetMulti(query: Query, backends: List[Backend]) extends MayFail2[Maybe[List[Result]]]
  }

  type P = MayFail1 :|: MayFail2 :|: PureProcess :|: NilDSL
  val  P = DSL.Make[P]
  type O2 = Maybe :&: Bulb

  def search3(input: String): OnionT[Free, P.Cop, O2, List[Result]] = {
    for {
      query <- MayFail1.Parse(input)         .freek[P].onionT[O2]
      b     <- PureProcess.MultiBackends     .freek[P].onion[O2]
      res   <- MayFail2.GetMulti(query, b)   .freek[P].onionT[Maybe :&: List :&: Bulb].peelRight
    } yield {
      res
    }
  }

  val a3: Free[P.Cop, Maybe[List[Result]]] = search3("plop").value
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment