An API can be treated as an algebra: a set of operations over data types, together with laws describing how those operations should behave. Writing type signatures first lets implementation follow from the types while temporarily setting aside domain details. section 7.3
A functional API becomes easier to design and reuse when you:
- Choose a small set of primitive operations, then derive familiar combinators such as map, flatMap, map2, and sequence. section 7.6 section 9.8
- State laws that constrain valid implementations and turn the API into a target for property-based testing. section 7.3 section 8.0
- Design the algebra independently from its interpreter, so representations can change without rewriting programs expressed through the API. section 9.4 section 7.6
- Iterate through types, sample uses, implementation attempts, and usability improvements rather than fixing every choice in advance. section 8.2.1 section 9.8
A parser API before its implementation
A JSON parser can be written against a Parsers interface using only primitive parsers and derived combinators. The parser describes the desired computation without knowing how parsers are represented; a concrete implementation can be supplied later, and improved error reporting can be added without changing the overall structure. section 9.4 section 9.8
def jsonParser[Err, Parser[+_]](
P: Parsers[Err, Parser] #1
): Parser[JSON] =
import P.* #2
val spaces = char(' ').many.slice #3
...
A compact Scala definition shows an API client receiving a Parsers interface, importing its operations, and assembling a JSON parser from combinators such as many and slice. section 9.4











































