{"action":"created","issue":{"url":"https://api.github.com/repos/non/cats/issues/671","labels_url":"https://api.github.com/repos/non/cats/issues/671/labels{/name}","comments_url":"https://api.github.com/repos/non/cats/issues/671/comments","events_url":"https://api.github.com/repos/non/cats/issues/671/events","html_url":"https://github.com/non/cats/pull/671","id":117376735,"number":671,"title":"Request to Include `cats.data.Coproduct` and `cats.free.Inject`","user":{"login":"raulraja","id":456796,"avatar_url":"https://avatars.githubusercontent.com/u/456796?v=3","gravatar_id":"","url":"https://api.github.com/users/raulraja","html_url":"https://github.com/raulraja","followers_url":"https://api.github.com/users/raulraja/followers","following_url":"https://api.github.com/users/raulraja/following{/other_user}","gists_url":"https://api.github.com/users/raulraja/gists{/gist_id}","starred_url":"https://api.github.com/users/raulraja/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/raulraja/subscriptions","organizations_url":"https://api.github.com/users/raulraja/orgs","repos_url":"https://api.github.com/users/raulraja/repos","events_url":"https://api.github.com/users/raulraja/events{/privacy}","received_events_url":"https://api.github.com/users/raulraja/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":9,"created_at":"2015-11-17T15:19:13Z","updated_at":"2015-11-19T00:38:07Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/non/cats/pulls/671","html_url":"https://github.com/non/cats/pull/671","diff_url":"https://github.com/non/cats/pull/671.diff","patch_url":"https://github.com/non/cats/pull/671.patch"},"body":"The following PR adds `cats.data.Coproduct` and `cats.free.Inject` largely based on those found in Scalaz as in [\"Data types a la carte\"](http://www.staff.science.uu.nl/~swier004/Publications/DataTypesALaCarte.pdf) (Swierstra 2008).\r\n\r\n`Coproduct` & `Inject` can be used to compose Free based Algebras where an Application is nothing but the Coproduct resulting from the interaction of it's algebras.\r\n\r\nIn other words:\r\n\r\n```scala\r\nimport cats.arrow.NaturalTransformation\r\nimport cats.data.{Xor, Coproduct}\r\nimport cats.free.{Inject, Free}\r\nimport cats.{Id, ~>}\r\nimport scala.collection.mutable.ListBuffer\r\n\r\n/* Handles user interaction */\r\nsealed trait Interact[A]\r\ncase class Ask(prompt: String) extends Interact[String]\r\ncase class Tell(msg: String) extends Interact[Unit]\r\n\r\n/* Represents persistence operations */\r\nsealed trait DataOp[A]\r\ncase class AddCat(a: String) extends DataOp[Unit]\r\ncase class GetAllCats() extends DataOp[List[String]]\r\n\r\ntype CatsApp[A] = Coproduct[DataOp, Interact, A]\r\n\r\ndef lift[F[_], G[_], A](fa: F[A])(implicit I: Inject[F, G]): Free[G, A] =\r\n  Free.liftF(I.inj(fa))\r\n\r\nclass Interacts[F[_]](implicit I: Inject[Interact, F]) {\r\n  def tell(msg: String): Free[F, Unit] = lift(Tell(msg))\r\n  def ask(prompt: String): Free[F, String] = lift(Ask(prompt))\r\n}\r\n\r\nobject Interacts {\r\n  implicit def interacts[F[_]](implicit I: Inject[Interact, F]): Interacts[F] = new Interacts[F]\r\n}\r\n\r\nclass DataSource[F[_]](implicit I: Inject[DataOp, F]) {\r\n  def addCat(a: String): Free[F, Unit] = lift[DataOp, F, Unit](AddCat(a))\r\n  def getAllCats: Free[F, List[String]] = lift[DataOp, F, List[String]](GetAllCats())\r\n}\r\n\r\nobject DataSource {\r\n  implicit def dataSource[F[_]](implicit I: Inject[DataOp, F]): DataSource[F] = new DataSource[F]\r\n}\r\n\r\ndef program(implicit I : Interacts[CatsApp], D : DataSource[CatsApp]) = {\r\n\r\n  import I._, D._\r\n\r\n  for {\r\n    cat <- ask(\"What's the kitty's name\")\r\n    _ <- addCat(cat)\r\n    cats <- getAllCats\r\n    _ <- tell(cats.toString)\r\n  } yield ()\r\n}\r\n```\r\nInterpreters omitted for simplicity but available in the free monads tutorial and Inject tests.\r\n\r\n@non @ceedubs thanks for your consideration. "},"comment":{"url":"https://api.github.com/repos/non/cats/issues/comments/157909785","html_url":"https://github.com/non/cats/pull/671#issuecomment-157909785","issue_url":"https://api.github.com/repos/non/cats/issues/671","id":157909785,"user":{"login":"adelbertc","id":1332980,"avatar_url":"https://avatars.githubusercontent.com/u/1332980?v=3","gravatar_id":"","url":"https://api.github.com/users/adelbertc","html_url":"https://github.com/adelbertc","followers_url":"https://api.github.com/users/adelbertc/followers","following_url":"https://api.github.com/users/adelbertc/following{/other_user}","gists_url":"https://api.github.com/users/adelbertc/gists{/gist_id}","starred_url":"https://api.github.com/users/adelbertc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/adelbertc/subscriptions","organizations_url":"https://api.github.com/users/adelbertc/orgs","repos_url":"https://api.github.com/users/adelbertc/repos","events_url":"https://api.github.com/users/adelbertc/events{/privacy}","received_events_url":"https://api.github.com/users/adelbertc/received_events","type":"User","site_admin":false},"created_at":"2015-11-19T00:38:07Z","updated_at":"2015-11-19T00:38:07Z","body":":+1: Thanks @raulraja , awesome PR"}}