Hi,
I am trying to apply the scalaz.stream library to a problem space involving
actors fetching resources on the web. I am not sure if the Process is the
right tool for this yet at all, as I am exploring the library.
Introduction
------------
Just to build up the problem a bit I have a few functions that seem to work:
//get a URI off the web ( or locally )
def get(uri: Rdf#URI): Process[Future,LinkedDataResource[Rdf]] = {
val url = uri.fragmentLess
val ldr: Future[LinkedDataResource[Rdf]] =
rww.execute(getLDPR(url)).map{gr=>LinkedDataResource(url,PointedGraph(uri,gr))}
await(ldr){o=>emit(o)}
}
//follow a relation in a graph
def follow(rel: Rdf#URI): Process1[LinkedDataResource[Rdf],LinkedDataResource[Rdf]] = {
await1[LinkedDataResource[Rdf]].flatMap{ldr=>
emitAll((ldr.resource/rel).toSeq).map{pg=>LinkedDataResource(ldr.location,pg)}
}
}
So this allows one to the following to find the members of the group
get(tpacGroup) |> follow(foaf.member)
Sequences of Futures
--------------------
The above is nice but not very useful, as it can be done much more efficiently
without Processes. What we really want to do is see if the URIs found by following
a link in a document is defined locally in the graph under consideration or remotely.
If it is remote, we'd like to GET those, and follow on from there.
So here I want to define a function ~> like this
def ~>(rel: Rdf#URI): Process[...?] = {
await1[LinkedDataResource[Rdf]].flatMap{ldr=>
val res = (ldr.resource/rel)
val local_remote = res.groupBy {
pg =>
foldNode(pg.pointer)(
uri => if (uri.fragmentLess == ldr.location) "local" else "remote",
bnode => "local",
lit => "local"
)
}
emitAll(local_remote("local").map(pg=>LinkedDataResource(ldr.location,pg)).toSeq) ++ {
val x = get(local_remote("remote").map(pg=>pg.pointer.asInstanceOf[Rdf#URI]).toSeq)
x
}
}
}
but I am already not quite sure what the signature for it should be. Probably
Process1[LinkedDataResource[Rdf],LinkedDataResource[Rdf]] because that is what
the follow( ) function is defined as and I'd like this to be used in the same way.
But as it calls a the get(...) function with the following signature things don't work out.
def get(uris: Seq[Rdf#URI]): Process[Future,LinkedDataResource[Rdf]] = {
val futures = uris.map { uri =>
val url = uri.fragmentLess
val ldr = rww.execute(getLDPR(url)).map { gr => LinkedDataResource(url, PointedGraph(uri, gr))}
ldr
}
futures ....
}
I want this to GET asynchronously all the resources and treat the
result as a Stream so that the next value is available as soon as a remote
fetch is finished.
I did in fact get this to work with Enumerators but I was wondering
reading chapter 15 of the book on Functional Programming if I would
gain some advantages doing this with Processes.
https://github.com/w3c/banana-rdf/blob/master/ldp/src/main/scala/LinkedResource.scala#L42
Henry
Social Web Architect
http://bblfish.net/