Functional Programming in Scala
Paul Chiusano and Runar Bjarnason
Foreword by Martin Odersky
  • September 2014
  • ISBN 9781617290657
  • 320 pages
  • printed in black & white

Leads to deep insights into the nature of computation.

From the Foreword by Martin Odersky, Creator of Scala

Functional Programming in Scala is a serious tutorial for programmers looking to learn FP and apply it to the everyday business of coding. The book guides readers from basic techniques to advanced topics in a logical, concise, and clear progression. In it, you'll find concrete examples and exercises that open up the world of functional programming.

Listen to this book in liveAudio! liveAudio integrates a professional voice recording with the book’s text, graphics, code, and exercises in Manning’s exclusive liveBook online reader. Use the text to search and navigate the audio, or download the audio-only recording for portable offline listening. You can purchase or upgrade to liveAudio here or in liveBook.

About the Technology

Functional programming (FP) is a style of software development emphasizing functions that don't depend on program state. Functional code is easier to test and reuse, simpler to parallelize, and less prone to bugs than other code. Scala is an emerging JVM language that offers strong support for FP. Its familiar syntax and transparent interoperability with Java make Scala a great place to start learning FP.

Table of Contents detailed table of contents




about this book

Part 1 Introduction to functional programming

1. What is functional programming?

1.1. The benefits of FP: a simple example

1.1.1. A program with side effects

1.1.2. A functional solution: removing the side effects

1.2. Exactly what is a (pure) function?

1.3. Referential transparency, purity, and the substitution model

1.4. Summary

2. Getting started with functional programming in Scala

2.1. Introducing Scala the language: an example

2.2. Running our program

2.3. Modules, objects, and namespaces

2.4. Higher-order functions: passing functions to functions

2.4.1. A short detour: writing loops functionally

2.4.2. Writing our first higher-order function

2.5. Polymorphic functions: abstracting over types

2.5.1. An example of a polymorphic function

2.5.2. Calling HOFs with anonymous functions

2.6. Following types to implementations

2.7. Summary

3. Functional data structures

3.1. Defining functional data structures

3.2. Pattern matching

3.3. Data sharing in functional data structures

3.3.1. The efficiency of data sharing

3.3.2. Improving type inference for higher-order functions

3.4. Recursion over lists and generalizing to higher-order functions

3.4.1. More functions for working with lists

3.4.2. Loss of efficiency when assembling list functions from simpler components

3.5. Trees

3.6. Summary

4. Handling errors without exceptions

4.1. The good and bad aspects of exceptions

4.2. Possible alternatives to exceptions

4.3. The Option data type

4.3.1. Usage patterns for Option

4.3.2. Option composition, lifting, and wrapping exception-oriented APIs

4.4. The Either data type

4.5. Summary

5. Strictness and laziness

5.1. Strict and non-strict functions

5.2. An extended example: lazy lists

5.2.1. Memoizing streams and avoiding recomputation

5.2.2. Helper functions for inspecting streams

5.3. Separating program description from evaluation

5.4. Infinite streams and corecursion

5.5. Summary

6. Purely functional state

6.1. Generating random numbers using side effects

6.2. Purely functional random number generation

6.3. Making stateful APIs pure

6.4. A better API for state actions

6.4.1. Combining state actions

6.4.2. Nesting state actions

6.5. A general state action data type

6.6. Purely functional imperative programming

6.7. Summary

Part 2 Functional design and combinator libraries

7. Purely functional parallelism

7.1. Choosing data types and functions

7.1.1. A data type for parallel computations

7.1.2. Combining parallel computations

7.1.3. Explicit forking

7.2. Picking a representation

7.3. Refining the API

7.4. The algebra of an API

7.4.1. The law of mapping

7.4.2. The law of forking

7.4.3. Breaking the law: a subtle bug

7.4.4. A fully non-blocking Par implementation using actors

7.5. Refining combinators to their most general form

7.6. Summary

8. Property-based testing

8.1. A brief tour of property-based testing

8.2. Choosing data types and functions

8.2.1. Initial snippets of an API

8.2.2. The meaning and API of properties

8.2.3. The meaning and API of generators

8.2.4. Generators that depend on generated values

8.2.5. Refining the Prop data type

8.3. Test case minimization

8.4. Using the library and improving its usability

8.4.1. Some simple examples

8.4.2. Writing a test suite for parallel computations

8.5. Testing higher-order functions and future directions

8.6. The laws of generators

8.7. Summary

9. Parser combinators

9.1. Designing an algebra, first

9.2. A possible algebra

9.2.1. Slicing and nonempty repetition

9.3. Handling context sensitivity

9.4. Writing a JSON parser

9.4.1. The JSON format

9.4.2. A JSON parser

9.5. Error reporting

9.5.1. A possible design

9.5.2. Error nesting

9.5.3. Controlling branching and backtracking

9.6. Implementing the algebra

9.6.1. One possible implementation

9.6.2. Sequencing parsers

9.6.3. Labeling parsers

9.6.4. Failover and backtracking

9.6.5. Context-sensitive parsing

9.7. Summary

Part 3 Common structures in functional design

10. Monoids

10.1. What is a monoid?

10.2. Folding lists with monoids

10.3. Associativity and parallelism

10.4. Example: Parallel parsing

10.5. Foldable data structures

10.6. Composing monoids

10.6.1. Assembling more complex monoids

10.6.2. Using composed monoids to fuse traversals

10.7. Summary

11. Monads

11.1. Functors: generalizing the map function

11.1.1. Functor laws

11.2. Monads: generalizing the flatMap and unit functions

11.2.1. The Monad trait

11.3. Monadic combinators

11.4. Monad laws

11.4.1. The associative law

11.4.2. Proving the associative law for a specific monad

11.4.3. The identity laws

11.5. Just what is a monad?

11.5.1. The identity monad

11.5.2. The State monad and partial type application

11.6. Summary

12. Applicative and traversable functors

12.1. Generalizing monads

12.2. The Applicative trait

12.3. The difference between monads and applicative functors

12.3.1. The Option applicative versus the Option monad

12.3.2. The Parser applicative versus the Parser monad

12.4. The advantages of applicative functors

12.4.1. Not all applicative functors are monads

12.5. The applicative laws

12.5.1. Left and right identity

12.5.2. Associativity

12.5.3. Naturality of product

12.6. Traversable functors

12.7. Uses of Traverse

12.7.1. From monoids to applicative functors

12.7.2. Traversals with State

12.7.3. Combining traversable structures

12.7.4. Traversal fusion

12.7.5. Nested traversals

12.7.6. Monad composition

12.8. Summary

Part 4 Effects and I/O

13. External effects and I/O

13.1. Factoring effects

13.2. A simple IO type

13.2.1. Handling input effects

13.2.2. Benefits and drawbacks of the simple IO type

13.3. Avoiding the StackOverflowError

13.3.1. Reifying control flow as data constructors

13.3.2. Trampolining: a general solution to stack overflow

13.4. A more nuanced IO type

13.4.1. Reasonably priced monads

13.4.2. A monad that supports only console I/O

13.4.3. Pure interpreters

13.5. Non-blocking and asynchronous I/O

13.6. A general-purpose IO type

13.6.1. The main program at the end of the universe

13.7. Why the IO type is insufficient for streaming I/O

13.8. Summary

14. Local effects and mutable state

14.1. Purely functional mutable state

14.2. A data type to enforce scoping of side effects

14.2.1. A little language for scoped mutation

14.2.2. An algebra of mutable references

14.2.3. Running mutable state actions

14.2.4. Mutable arrays

14.2.5. A purely functional in-place quicksort

14.3. Purity is contextual

14.3.1. What counts as a side effect?

14.4. Summary

15. Stream processing and incremental I/O

15.1. Problems with imperative I/O: an example

15.2. Simple stream transducers

15.2.1. Creating processes

15.2.2. Composing and appending processes

15.2.3. Processing files

15.3. An extensible process type

15.3.1. Sources

15.3.2. Ensuring resource safety

15.3.3. Single-input processes

15.3.4. Multiple input streams

15.3.5. Sinks

15.3.6. Effectful channels

15.3.7. Dynamic resource allocation

15.4. Applications

15.5. Summary


What's inside

  • Functional programming concepts
  • The whys and hows of FP
  • How to write multicore programs
  • Exercises and checks for understanding

About the reader

This book assumes no prior experience with functional programming. Some prior exposure to Scala or Java is helpful.

About the authors

Paul Chiusano and Rúnar Bjarnason are recognized experts in functional programming with Scala and are core contributors to the Scalaz library.

placing your order...

Don't refresh or navigate away from the page.
print book $29.99 $44.99 pBook + eBook + liveBook
Additional shipping charges may apply
Prints and ships within 3-5 days
Functional Programming in Scala (print book) added to cart
continue shopping
go to cart

eBook $24.99 $35.99 3 formats + liveBook
Functional Programming in Scala (eBook) added to cart
continue shopping
go to cart

Add liveAudio for only $19.99
Prices displayed in rupees will be charged in USD when you check out.

FREE domestic shipping on three or more pBooks