liveBook · Manning

Console

As explained in Functional Programming in Scala, Second Edition

Console is an algebraic data type representing primitive console-interaction operations supported by a free program.

Console is an algebraic data type for primitive console operations. It has two cases: ReadLine, producing Console[Option[String]], and PrintLine(line), producing Console[Unit]. section 13.4.2

Listing 13.6 Creating our Console type
enum Console[A]:
  case ReadLine extends Console[Option[String]]
  case PrintLine(line: String) extends Console[Unit]
 
  def toPar: Par[A] = this match                             #1
    case ReadLine => Par.lazyUnit(Try(readLine()).toOption)
    case PrintLine(line) => Par.lazyUnit(println(line))
 
  def toThunk: () => A = this match                          #2
    case ReadLine => () => Try(readLine()).toOption
    case PrintLine(line) => () => println(line)

The definition keeps console requests explicit while supplying interpreters for parallel computation and delayed execution. section 13.4.2

Embedding Console actions in Free yields programs restricted to console I/O. Free sequences requests without executing them; interpretation translates each request into a target monad such as Par or Function0. Console itself cannot implement flatMap because a ReadLine result does not exist until interpretation. section 13.4.2

A console-only program

val f1: Free[Console, Option[String]] = for _ <- printLn("I can only interact with the console.") ln <- readLn yield ln The program describes output followed by input, while its interpreter decides whether those requests perform real I/O. section 13.4.3

Interpreters can replace real console effects with Reader or State simulations: tests may ignore output, provide predetermined input, or track input and output buffers. The same restricted program can therefore support testing and execution. section 13.4.3

Console also names a capability interface whose operations return values in a chosen effect type. This reduces suspension boilerplate while preserving least-powerful programs that cannot access unrelated effects. section 13.6

How Functional Programming in Scala, Second Edition covers it

How deep it goes
Defines two operations, their interpreters, Free embedding, and target-monad translation, but defers execution semantics to interpreters.
Examples
Uses ReadLine, PrintLine, a greeting program, and simulated input-output buffers as concrete examples.
What it assumes
Assumes algebraic data types, higher-kinded types, Free, and monads while demonstrating console operations from their primitive cases.
What you can do after
Build it from scratch as a restricted Free program and interpret it as real, delayed, or simulated console computation.
How it connects
Connects Console with Free, interpreters, monads, Par, Function0, Reader, State, and the principle of least power.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Functional Programming in Scala, Second Edition. The section links point to the parts of the book it draws on.