The cameraman has told me that the batteries went flat through the
second talk (Writer monad), sorry.
--
Tony Morris
http://tmorris.net/
Well, categorically it is formulated the simplest way: T^Env, with
const as unit and curry of the diagonal as join.
Used the notion immediately in my, hmm, java code, for sessions dependency.
Thanks,
-Vlad
That example slide really pulls it all together.
Same deal, great talk, its a shame the end scala example (the extra 30
minutes down the pub time) wasn't covered though.
That example slide really pulls it all together.
“former” ? Lucky you!
Let's pass the configuration to every function that requires it, including those for which it is simply passed on.
def lift3ConfigReader[A, B, C, D](f: A => B => C => D):
ConfigReader[A] =>
ConfigReader[B] =>
ConfigReader[C] =>
ConfigReader[D] =
a => b => c =>
for{
aa <- a
bb <- b
cc <- c
} yield f(aa)(bb)(cc)
I Tony,
thanks for this great intro to Reader Monads [1] I went through the presentation, watched the video, and bought the mug. ;-)But I have a few questions remaining.
1) You start your talk by saying that one can solve the following problem
Let's pass the configuration to every function that requires it, including those for which it is simply passed on.Indeed that is exactly the type of problem I had with Read-Write-Web project I am working on [2]. I had a WebProxy class where I hadan instance object that I had to pass to all kinds of other objects which just passed it on until it was finally useful. I replaced it now witha simple (static) object and the code feels a lot better already. But now we loose configuration. So I was intrigued to see if I could usethe reader monad to do all the configurations of the server. Do you have some pointers to some examples that flesh this out in moreconcrete examples by now?
2) You mention the following code, and explain how A, B, C, D could be any kind of object,like ints, or floats, or strings, or more complex objects. But those objects don't have either map or flatmap methods. I don't thinkyou explained how they got those methods. Did you import some scalaz implicit library?
def lift3ConfigReader[A, B, C, D](f: A => B => C => D):
ConfigReader[A] =>
ConfigReader[B] =>
ConfigReader[C] =>
ConfigReader[D] =
a => b => c =>
for{
aa <- a
bb <- b
cc <- c
} yield f(aa)(bb)(cc)
I think those were the two questions I had.
Henry
[1] presentation: http://dl.dropbox.com/u/7810909/docs/reader-monad/chunk-html/index.htmlvideo: http://vimeo.com/20674558
Hi mate.
On 12/06/2011 08:13 PM, bblfish wrote:I Tony,
thanks for this great intro to Reader Monads [1] I went through the presentation, watched the video, and bought the mug. ;-)But I have a few questions remaining.
1) You start your talk by saying that one can solve the following problem
Let's pass the configuration to every function that requires it, including those for which it is simply passed on.Indeed that is exactly the type of problem I had with Read-Write-Web project I am working on [2]. I had a WebProxy class where I hadan instance object that I had to pass to all kinds of other objects which just passed it on until it was finally useful. I replaced it now witha simple (static) object and the code feels a lot better already. But now we loose configuration. So I was intrigued to see if I could usethe reader monad to do all the configurations of the server. Do you have some pointers to some examples that flesh this out in moreconcrete examples by now?
Yes, this sounds exactly like the problem that the reader monad would solve.
I don't have more examples and I could surely whip some up easily, but it's difficult to do this without knowing exactly what is going to help your understanding. Maybe I will answer the next question and that will help.
The basic intuition of model-theoretic semantics is that asserting a sentence makes a claim about theworld: it is another way of saying that the world is, in fact, so arranged as to be an interpretation which makes the sentence true. In other words, an assertion amounts to stating a constrainton the possible ways the world might be. Notice that there is no presumption here that any assertion contains enough information to specify a single unique interpretation. It is usually impossible to assert enough in any language to completely constrain the interpretations to a single possible world, so there is no such thing as 'the' unique interpretation of an RDF graph. In general, the larger an RDF graph is - the more it says about the world - then the smaller the set of interpretations that an assertion of the graph allows to be true - the fewer the ways the world could be, while making the asserted graph true of it.
So a program that was once using, say Int, then we transformed to say Identity[Int] (just for giggles, not because it was useful), we could then transform to ConfigReader[Int] and this time, we get the advantage that our values (Int, etc.) have access to an environment (Config), but we also have the advantage that we do not need to deal directly with the "passing of this environment" since the for-comprehension takes care of that for us -- after all, syntactically, they are much the same as a regular program. This makes the library code and the client code much less complex.
Other monads in this direction that have other types of uses are:
* State
case class State[S, A](f: S => (S, A))
* Writer
case class Writer[W, A](w: W, a: A) // flatMap requires a Monoid[W]
* ReaderWriterState (aka RWS)
case class RWS[R, W, S, A](f: R => S => (A, S, W))
* their transformer versions (I mention this only because in practice, they pop up regularly)
** case class StateT[S, F[_], A](f: S => F[(S, A)])
** case class WriterT[W, F[_], A](x: F[(W, A)])
** case class RWST[R, W, S, F[_], A](f: R => S => F[(A, S, W)])
HTH.
I think those were the two questions I had.
Henry
[1] presentation: http://dl.dropbox.com/u/7810909/docs/reader-monad/chunk-html/index.htmlvideo: http://vimeo.com/20674558
-- Tony Morris http://tmorris.net/
I think you should take a look at some of Greg Meredith's stuff - he's
got a upcoming book (which I can't find a link to) and a number of
blog posts [1] and videos [2] about monads and the web :)
Hope some of this is of interest!
[1] http://biosimilarity.blogspot.com/
[2] http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Greg-Meredith-Monadic-Design-Patterns-for-the-Web-Introduction-to-Monads
uhm, there are other reasons to avoid singletons.
testing often ends up requiring you to have more than one www.
sincerely.
This isn't a defence of singletons, but - if happen to find yourself having to write tests for code that uses them, you might be interested to know that ScalaMock can mock singletons...
:-)
--
paul.butcher->msgCount++
Snetterton, Castle Combe, Cadwell Park...
Who says I have a one track mind?
http://www.paulbutcher.com/
LinkedIn: http://www.linkedin.com/in/paulbutcher
MSN: pa...@paulbutcher.com
AIM: paulrabutcher
Skype: paulrabutcher
-jason
> Here's another example that shows how to use this pattern:
> https://gist.github.com/1395578
Thanks for posting this comparison. I've asked a question about this
reader monad video example some time ago[1], and I still fail to
understand how this style is applied at a scale above method level -
perhaps you can enlighten me.
Just adding one more method invocation level to your example:
object Config0 {
def subFragment1(contextRoot: String) =
<a href={contextRoot + "/foo"}>foo</a>
def fragment1(contextRoot: String) =
<ul>{for(i <- (1 to 3))
yield <li>{subFragment1(contextRoot)}</li>}</ul>
def html(contextRoot: String) =
<html><body>{fragment1(contextRoot)}</body></html>
def render = html("/c1")
}
object Config1 {
val contextRoot =
new scala.util.DynamicVariable[String]("")
def subFragment1 =
<a href={contextRoot.value + "/foo"}>foo</a>
def fragment1 =
<ul>{for(i <- (1 to 3))
yield <li>{subFragment1}</li>}</ul>
def html = <html><body>{fragment1}</body></html>
def render = contextRoot.withValue("/c1") { html }
}
What would the idiomatic implementation for Config2 (the reader monad
variant) look like?
Best regards,
Patrick
[1] http://groups.google.com/group/scala-user/msg/a3ca9f967968ed09
45 case class GraphReader[A](extract: Resource => Validation[scala.Throwable,A]) {
46 def map[B](g: A => B) = GraphReader(r => extract(r).map(g(_)))
47 def flatMap[B](g: A => GraphReader[B]): GraphReader[B] = GraphReader(r => extract(r).map(g(_)).flatMap(_.extract(r)))
48 }
96 def findDefinedPeople(m: Resource): Validation[scala.Throwable,Set[IdPerson]] = {
97 for (gr<-m.get) yield {
98 for (st <- gr.listStatements(null,RDF.`type`,FOAF.Person).asScala;
99 val subj = st.getSubject;
100 if (subj.isURIResource && subj.toString.startsWith(m.name.toString));
101 st2 <- gr.listStatements(subj, FOAF.name,null).asScala
102 ) yield {
103 new IdPerson(subj)
104 }
105 }.toSet
106 }
132 val definedPeopleRd = new GraphReader[Set[IdPerson]](Extractors.findDefinedPeople)
149 // extract the people who are defined in the graph (rarely more than one)
150 for (people <- definedPeopleRd.extract(new URL(url));
151 p <- people) {
153 }
154 out.println
134 val definedPeopleFriends = definedPeopleRd.flatMap(people =>GraphReader[Set[IdPerson]]{
135 resource: Resource =>
136 resource.get.map(gr=>
137 for ( p <- people;
138 st <- gr.listStatements(p.webid, FOAF.knows, null).asScala ;
139 val friend = st.getObject;
140 if (friend.isURIResource)
141 ) yield IdPerson(friend.asInstanceOf[JResource])
142 )
143 } )
52 case class IdPerson(webid: JResource) {