Skip to content

Instantly share code, notes, and snippets.

@Mortimerp9
Last active October 13, 2017 16:12
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mortimerp9/5380105 to your computer and use it in GitHub Desktop.
Save Mortimerp9/5380105 to your computer and use it in GitHub Desktop.
Sample code for the following post https://coderwall.com/p/pdrz7q
object test {
/**
* The companion object
*/
object Reader {
/**
* automatically wrap a function in a reader
*/
implicit def reader[From, To](block: From => To) = Reader[From, To](block)
/**
* create a reader that does not really depend on anything. This is a way of wrapping an already computed result (like a failure) within a Reader when we need such a return type.
*/
def pure[From, To](a: To) = Reader((c: From) => a)
/**
* resolve a reader
*/
def withDependency[F, T](dep: F)(reader: Reader[F, T]): T = reader(dep)
}
/**
* The reader Monad
*/
case class Reader[-From, +To](wrappedF: From => To) {
def apply(c: From) = wrappedF(c)
def map[ToB](transformF: To => ToB): Reader[From, ToB] =
Reader(c => transformF(wrappedF(c)))
def flatMap[FromB <: From, ToB](f: To => Reader[FromB, ToB]): Reader[FromB, ToB] =
Reader(c => f(wrappedF(c))(c))
}
//Model
case class User(val id: Long)
case class Post(val title: String)
//Connections
trait UserConnection {
def readUser(id: Long): Option[User] = Some(User(id))
}
trait PostConnection {
def readPosts(user: User): Seq[Post] = Seq(Post("test"), Post("test2"))
}
import Reader._
//a concrete connection
type UserPostConn = UserConnection with PostConnection
class RealConn extends UserConnection with PostConnection {}
val conn = new RealConn
/**
* all the posts from a user please
*/
def userPosts(userID: Long): Reader[UserPostConn, Seq[Post]] = reader { conn =>
(conn.readUser(userID) map { user =>
conn.readPosts(user)
}) getOrElse (List()) //getting rid of the Option just to simplify the code in this article
}
/**
* just the titles, thank you
*/
def titles(id: Long) = userPosts(id).map { postIterable =>
postIterable.map(_.title)
}
/**
* unwrap the reader given a concrete dependency
*/
withDependency(conn) { titles(10l) }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment