Resource finalization releases an acquired resource after its computation completes or fails. Separate acquisition, use, and release, then attach release with Stream.onComplete so cleanup belongs to the computation rather than an ad hoc success path. section 15.3.2
Reading and closing a file
Define acquire(path) as Task(Source.fromFile(path)), use(source) as a stream over source.getLines, and release(source) as Task(source.close()). Compose them with use(resource).onComplete(Stream.eval(release(resource))). The cleanup stream is attached to the use stream, including when stream evaluation reports an error. section 15.3.2
The pattern makes the lifecycle explicit:
- Acquire the resource inside Task. section 15.3.2
- Represent consumption as a Stream[Task, A]. section 15.3.2
- Attach release with onComplete rather than scattering close calls through processing code. section 15.3.2
