Last active
September 29, 2016 22:09
-
-
Save yilinwei/c3536b51ecb9e26e58c1704aed36afed to your computer and use it in GitHub Desktop.
Free circumvention
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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