or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

application.mdconcurrency.mdindex.mdio.mdresources.mdtype-classes.md

type-classes.mddocs/

0

# Effect Type Classes

1

2

Cats Effect provides a hierarchy of type classes that define capabilities for synchronous, asynchronous, and concurrent effects. This enables abstraction over different effect types while maintaining type safety and composability.

3

4

## Capabilities

5

6

### Bracket Type Class

7

8

Base type class for resource management and safe cleanup operations.

9

10

```scala { .api }

11

/**

12

* Type class for resource management with bracket pattern

13

*/

14

trait Bracket[F[_], E] extends MonadError[F, E] {

15

/** Bracket with detailed exit case information */

16

def bracketCase[A, B](acquire: F[A])(use: A => F[B])(release: (A, ExitCase[E]) => F[Unit]): F[B]

17

18

/** Simple bracket pattern (implemented) */

19

def bracket[A, B](acquire: F[A])(use: A => F[B])(release: A => F[Unit]): F[B] =

20

bracketCase(acquire)(use)((a, _) => release(a))

21

22

/** Make an effect uncancelable (implemented) */

23

def uncancelable[A](fa: F[A]): F[A] =

24

bracket(fa)(pure)(_ => unit)

25

26

/** Always execute finalizer (implemented) */

27

def guarantee[A](fa: F[A])(finalizer: F[Unit]): F[A] =

28

bracket(unit)(_ => fa)(_ => finalizer)

29

30

/** Execute finalizer with exit case (implemented) */

31

def guaranteeCase[A](fa: F[A])(finalizer: ExitCase[E] => F[Unit]): F[A] =

32

bracketCase(unit)(_ => fa)((_, e) => finalizer(e))

33

34

/** Execute finalizer only on cancellation (implemented) */

35

def onCancel[A](fa: F[A])(finalizer: F[Unit]): F[A] =

36

guaranteeCase(fa) {

37

case ExitCase.Canceled => finalizer

38

case _ => unit

39

}

40

}

41

42

/**

43

* Exit case information for resource cleanup

44

*/

45

sealed abstract class ExitCase[+E] extends Product with Serializable

46

47

object ExitCase {

48

case object Completed extends ExitCase[Nothing]

49

final case class Error[+E](e: E) extends ExitCase[E]

50

case object Canceled extends ExitCase[Nothing]

51

}

52

```

53

54

### Sync Type Class

55

56

Base type class for synchronous effects that can suspend side-effecting computations.

57

58

```scala { .api }

59

/**

60

* Type class for synchronous effects with suspension capabilities

61

*/

62

trait Sync[F[_]] extends BracketThrow[F] with Defer[F] {

63

/** Suspend an F computation for stack safety (deprecated, use defer) */

64

def suspend[A](fa: => F[A]): F[A]

65

66

/** Suspend an F computation for stack safety (preferred over suspend) */

67

def defer[A](fa: => F[A]): F[A]

68

69

/** Suspend a side-effecting computation */

70

def delay[A](thunk: => A): F[A]

71

}

72

73

/** Type alias for Bracket[F, Throwable] */

74

type BracketThrow[F[_]] = Bracket[F, Throwable]

75

76

object Sync {

77

def apply[F[_]](implicit F: Sync[F]): Sync[F] = F

78

79

/** Syntax for delay operations */

80

implicit class SyncOps[F[_], A](fa: F[A])(implicit F: Sync[F]) {

81

def delayBy(duration: FiniteDuration): F[A]

82

}

83

}

84

```

85

86

**Usage Examples:**

87

88

```scala

89

def readFile[F[_]: Sync](path: String): F[String] =

90

Sync[F].delay {

91

scala.io.Source.fromFile(path).mkString

92

}

93

94

def safeComputation[F[_]: Sync](input: Int): F[Int] =

95

Sync[F].defer {

96

if (input < 0) Sync[F].raiseError(new IllegalArgumentException("Negative input"))

97

else Sync[F].delay(input * 2)

98

}

99

```

100

101

### Async Type Class

102

103

Type class for asynchronous effects that can handle callback-based operations.

104

105

```scala { .api }

106

/**

107

* Type class for asynchronous effects with callback support

108

*/

109

trait Async[F[_]] extends Sync[F] with LiftIO[F] {

110

/** Create an async effect from a callback */

111

def async[A](k: (Either[Throwable, A] => Unit) => Unit): F[A]

112

113

/** Create an async effect with effectful registration */

114

def asyncF[A](k: (Either[Throwable, A] => Unit) => F[Unit]): F[A]

115

116

/** An effect that never completes (implemented via async) */

117

def never[A]: F[A] = async(_ => ())

118

}

119

120

object Async {

121

def apply[F[_]](implicit F: Async[F]): Async[F] = F

122

123

/** Shift execution to a different ExecutionContext */

124

def shift[F[_]](ec: ExecutionContext)(implicit F: Async[F]): F[Unit]

125

126

/** Convert a Future to F */

127

def fromFuture[F[_], A](fa: F[Future[A]])(implicit F: Async[F]): F[A]

128

129

/** Memoize an effect */

130

def memoize[F[_], A](f: F[A])(implicit F: Async[F]): F[F[A]]

131

}

132

```

133

134

**Usage Examples:**

135

136

```scala

137

def httpRequest[F[_]: Async](url: String): F[String] =

138

Async[F].async { callback =>

139

// Simulate async HTTP request

140

val client = new AsyncHttpClient()

141

client.get(url) { response =>

142

callback(Right(response.body))

143

}

144

}

145

146

def delayedComputation[F[_]: Async](duration: FiniteDuration): F[Unit] =

147

Async[F].async { callback =>

148

val timer = new Timer()

149

timer.schedule(new TimerTask {

150

def run(): Unit = callback(Right(()))

151

}, duration.toMillis)

152

}

153

```

154

155

### Concurrent Type Class

156

157

Type class for concurrent effects with fiber support and cancellation.

158

159

```scala { .api }

160

/**

161

* Type class for concurrent effects with fiber support

162

*/

163

trait Concurrent[F[_]] extends Async[F] {

164

/** Start a fiber running the given effect */

165

def start[A](fa: F[A]): F[Fiber[F, A]]

166

167

/** Race two effects, returning winner and loser fiber */

168

def racePair[A, B](fa: F[A], fb: F[B]): F[Either[(A, Fiber[F, B]), (Fiber[F, A], B)]]

169

170

/** Race two effects, returning the first to complete (implemented) */

171

def race[A, B](fa: F[A], fb: F[B]): F[Either[A, B]] =

172

flatMap(racePair(fa, fb)) {

173

case Left((a, fiberB)) => map(fiberB.cancel)(_ => Left(a))

174

case Right((fiberA, b)) => map(fiberA.cancel)(_ => Right(b))

175

}

176

177

/** Create a cancelable effect (implemented) */

178

def cancelable[A](k: (Either[Throwable, A] => Unit) => CancelToken[F]): F[A]

179

180

/** Create background resource (implemented) */

181

def background[A](fa: F[A]): Resource[F, F[A]] =

182

Resource.make(start(fa))(_.cancel).map(_.join)

183

}

184

185

object Concurrent {

186

def apply[F[_]](implicit F: Concurrent[F]): Concurrent[F] = F

187

188

/** Timeout an effect */

189

def timeout[F[_], A](fa: F[A], duration: FiniteDuration)(implicit F: Concurrent[F], timer: Timer[F]): F[A]

190

191

/** Timeout with fallback */

192

def timeoutTo[F[_], A](fa: F[A], duration: FiniteDuration, fallback: F[A])(implicit F: Concurrent[F], timer: Timer[F]): F[A]

193

}

194

```

195

196

**Usage Examples:**

197

198

```scala

199

def parallelProcessing[F[_]: Concurrent](items: List[Item]): F[List[Result]] = {

200

val fibers = items.traverse(item => processItem(item).start)

201

fibers.flatMap(_.traverse(_.join))

202

}

203

204

def raceWithTimeout[F[_]: Concurrent: Timer, A](fa: F[A], timeout: FiniteDuration): F[Either[A, Unit]] =

205

Concurrent[F].race(fa, Timer[F].sleep(timeout))

206

```

207

208

### Bracket Type Class

209

210

Type class for resource management with automatic cleanup.

211

212

```scala { .api }

213

/**

214

* Type class for resource management with bracket operations

215

*/

216

trait Bracket[F[_], E] extends MonadError[F, E] {

217

/** Bracket resource management pattern */

218

def bracket[A, B](acquire: F[A])(use: A => F[B])(release: A => F[Unit]): F[B]

219

220

/** Bracket with access to exit case */

221

def bracketCase[A, B](acquire: F[A])(use: A => F[B])(release: (A, ExitCase[E]) => F[Unit]): F[B]

222

223

/** Ensure a finalizer always runs */

224

def guarantee[A](fa: F[A])(finalizer: F[Unit]): F[A]

225

226

/** Guarantee with access to exit case */

227

def guaranteeCase[A](fa: F[A])(finalizer: ExitCase[E] => F[Unit]): F[A]

228

229

/** Make an effect uncancelable */

230

def uncancelable[A](fa: F[A]): F[A]

231

}

232

233

/**

234

* Exit case for bracket operations

235

*/

236

sealed abstract class ExitCase[+E]

237

object ExitCase {

238

case object Completed extends ExitCase[Nothing]

239

case class Error[E](e: E) extends ExitCase[E]

240

case object Canceled extends ExitCase[Nothing]

241

}

242

```

243

244

**Usage Examples:**

245

246

```scala

247

def withResource[F[_]: Bracket[*[_], Throwable], A, B](

248

acquire: F[A]

249

)(use: A => F[B])(release: A => F[Unit]): F[B] =

250

Bracket[F, Throwable].bracket(acquire)(use)(release)

251

252

def safeFileOperation[F[_]: Bracket[*[_], Throwable]](path: String): F[String] =

253

Bracket[F, Throwable].bracket(

254

acquire = Sync[F].delay(new FileInputStream(path))

255

)(

256

use = stream => Sync[F].delay(/* read from stream */)

257

)(

258

release = stream => Sync[F].delay(stream.close())

259

)

260

```

261

262

### Effect Execution Type Classes

263

264

Type classes for executing effects in different contexts.

265

266

```scala { .api }

267

/**

268

* Type class for effects that can be executed asynchronously

269

*/

270

trait Effect[F[_]] extends Async[F] {

271

def runAsync[A](fa: F[A])(cb: Either[Throwable, A] => IO[Unit]): SyncIO[Unit]

272

}

273

274

/**

275

* Type class for effects that can be executed synchronously

276

*/

277

trait SyncEffect[F[_]] extends Effect[F] {

278

def runSync[A](fa: F[A]): A

279

}

280

281

/**

282

* Type class for concurrent effects that can be executed with cancellation

283

*/

284

trait ConcurrentEffect[F[_]] extends Concurrent[F] with Effect[F] {

285

def runCancelable[A](fa: F[A])(cb: Either[Throwable, A] => IO[Unit]): SyncIO[CancelToken[SyncIO]]

286

}

287

288

/**

289

* Type class for lifting IO into other effect types

290

*/

291

trait LiftIO[F[_]] {

292

def liftIO[A](ioa: IO[A]): F[A]

293

}

294

```

295

296

### Utility Type Classes

297

298

Additional type classes for timing and context management.

299

300

```scala { .api }

301

/**

302

* Type class for time-based operations

303

*/

304

trait Timer[F[_]] {

305

def clock: Clock[F]

306

def sleep(duration: FiniteDuration): F[Unit]

307

}

308

309

/**

310

* Type class for accessing time

311

*/

312

trait Clock[F[_]] {

313

def realTime(unit: TimeUnit): F[Long]

314

def monotonic(unit: TimeUnit): F[Long]

315

}

316

317

/**

318

* Type class for managing execution context

319

*/

320

trait ContextShift[F[_]] {

321

def shift: F[Unit]

322

def evalOn[A](ec: ExecutionContext)(fa: F[A]): F[A]

323

}

324

```

325

326

## Types

327

328

```scala { .api }

329

/**

330

* Type aliases for common bracket patterns

331

*/

332

type BracketThrow[F[_]] = Bracket[F, Throwable]

333

type ApplicativeThrow[F[_]] = ApplicativeError[F, Throwable]

334

type MonadThrow[F[_]] = MonadError[F, Throwable]

335

336

/**

337

* Cancellation token type

338

*/

339

type CancelToken[F[_]] = F[Unit]

340

341

/**

342

* Fiber handle for concurrent computations

343

*/

344

abstract class Fiber[F[_], A] {

345

def join: F[A]

346

def cancel: CancelToken[F]

347

}

348

```