Is there a continuation type for wrapping a run block, for example (Ctx => R) => R or (=> R) => R?

I am looking for a type that would allow me to imagine the context in which the code snippet is executed. For example:

def withinContext[R]: ((=> R) => R) = (inner) => { initializeSomeResource() try { inner } finally { releaseTheResource() } } 

which can then be used simply as

 withinContext { ... } 

Or, if the inner block of code needs some information from the context, generalize it as

 def withinContext[R]: ((Ctx => R) => R) = ... 

Their use cases roughly correspond to Haskell bracket_ and bracket .

I could use the types (=> R) => R and (A => R) => R directly, but then I do not have utility functions to combine such context wrappers, so I wonder if there is something like that already exists in Scala ecosystem

Closes what I know, scala.util.control.Exception.Catch , which provides nice functions for building and merging Catch instances, but there seems to be no way to start any initialization before executing the inner block. In addition (this is not so important for my use case), it does not allow giving a parameter to internal calculation, as in the case (A => R) => R

Type (A => R) => R is a continuation of the monad corresponding to Haskell ContT r IO a , but I could not find an implementation of the continuation of the monad in any Scala standard (it may be hidden somewhere deep in Scalas where I missed it) .

+5
scala continuations
source share
1 answer

I do such things quite often for use with the Specs2 test code. Essentially, we want some context to set up the code block environment. The idiom I use is this:

 def contextName[TYPE,RSRC](doit: (RSRC) => TYPE) : TYPE = { val thing : RSRC = acquireResource(args) try doit(thing) finally releaseResource(thing) } 

I understand that you are trying to continue the continuation, but I must ask: why? The idiom I just gave is a continuation of a monad like (Rsrc => TYPE) => TYPE, and it can be used in the same way as you suggested with withContext . For example, the real use case from the ReactiveMongo context object that I wrote:

 def withDatabase[T](dbName: String)(doit: (DefaultDB) => T) : T = { val db = connection.db(dbName) try doit(db) finally db.drop() } 

Gets the database, passes it on, and then deletes the database when it is running, even if the continuation throws an exception. It is used as follows:

 val numCollections = withDatabase("foo") { db => db.collectionNames.map { list => list.size } } 

Which simply uses the database to get the (future) number of collections in the database.

Hope this helps.

0
source share

All Articles