package scalaz import java.io.{OutputStream, InputStream} import java.sql.{PreparedStatement, ResultSet, Statement, Connection} sealed trait Resource[T] { def close(t: T): Unit } object Resource { implicit val ResourceContravariant: Contravariant[Resource] = new Contravariant[Resource] { def contramap[A, B](r: Resource[A], f: B => A) = new Resource[B] { def close(b: B) = r close (f(b)) } } implicit val InputStreamResource: Resource[InputStream] = new Resource[InputStream] { def close(c: InputStream) = c.close } implicit val OutputStreamResource: Resource[OutputStream] = new Resource[OutputStream] { def close(c: OutputStream) = c.close } implicit val SQLConnectionResource: Resource[Connection] = new Resource[Connection] { def close(c: Connection) = c.close } implicit val SQLStatementResource: Resource[Statement] = new Resource[Statement] { def close(c: Statement) = c.close } implicit val SQLPreparedStatementResource: Resource[PreparedStatement] = new Resource[PreparedStatement] { def close(c: PreparedStatement) = c.close } implicit val SQLResultSetResource: Resource[ResultSet] = new Resource[ResultSet] { def close(c: ResultSet) = c.close } } trait Resources { def resource[T](cl: T => Unit): Resource[T] = new Resource[T] { def close(t: T) = cl(t) } def withResource[T, R]( value: => T , evaluate: T => R , whenComputing: Throwable => R = (t: Throwable) => throw t , whenClosing: Throwable => Unit = _ => () )(implicit r: Resource[T]): R = try { val u = value try { evaluate(u) } finally { try { r close u } catch { case ex => whenClosing(ex) } } } catch { case ex => whenComputing(ex) } }