Skip to content

Instantly share code, notes, and snippets.

@yilinwei
Last active September 29, 2016 22:09
Show Gist options
  • Save yilinwei/c3536b51ecb9e26e58c1704aed36afed to your computer and use it in GitHub Desktop.
Save yilinwei/c3536b51ecb9e26e58c1704aed36afed to your computer and use it in GitHub Desktop.
Free circumvention
//Consider the following DSL for a representation of something which can have a get and a put
case class Get(key: String) extends DSL[String]
case class Put(key: String, value: String) extends DSL[String]
//When using it like,
for {
v <- lift(Get(key))
_ <- lift(Put(key, v))
} yield v
/*
The only meaningful constraint that we can possible know of this particular bit of composition is that F[_] is
going to be a lawful Monad. Consider the equivalent using MTL,
*/
def get[F[_] : MonadReader[Map[String, String]]](key: String): F[String] = ask.map(_.get(key))
def put[F[_] : MonadState[Map[String, String]]](key: String, value: String): F[Unit] = modify(_ + (k + v))
/*
These two signatures constrain the end program flow more than the Free equivalent - for one thing we know that
F[_] not only has to obey the Monad laws, but it also has to obey the MonadReader laws. As the end user, we can
now reason when I have a HOF what this function can do much more clearly. With the equivalent of the Free, it's just not
possible and hence you essentially lose the ability to capture whatever your freeing (i.e. the map and flatMap) in a lawful way.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment