![]() |
||
---|---|---|
console | ||
project | ||
src | ||
.gitignore | ||
.scalafmt.conf | ||
README.md | ||
build.sbt |
README.md
Embracing Nondeterminism
This code accompanies a blog series covering functional programming idioms for managing nondeterminism and unknown states in production code. Please follow the series for a full explanation of the concepts represented by the code in this repository:
- Part 1: Contexts and Effects
- Part 2: Permitting or Halting Computation
- Part 3: Imperative Computation
Structure of the repository
Scala packages under src/main/scala:green.thisfieldwas.embracingnondeterminism
data
contains commonly-used contexts that Scala defines in its own Standard Library, such asEither
,List
, andOption
and includesId
andNonEmptyList
. These code examples demonstrate different encodings of presence as the effects of operations and stand to illustrate how idioms in the series may be implemented across varying types. TheFunctor
typeclass is found here as well.extractables
contains illustrations of abstraction over presence using subtype polymorphism with abbreviated definitions of the classes defined in thedata
package. These exist to highlight the value in usingFunctor
as a design pattern.
Scala packages under src/test/scala:green.thisfieldwas.embracingnondeterminism
data
contains specs for each of the effect types as well as "laws" tests which assert that the associated effect type is well-defined for particular typeclasses, such asFunctor
.extractables
contains specs and property checks for theextractables
classes to illustrate how they work and how their abstractions break down.stdlib
contains property checks to illustrate how classes in the Scala Standard Library conform to typeclass laws themselves, and highlight that you, the reader of this series, have been using some of these concepts for some time.util
contains utility classes to aid in testing.
Using code and navigating imports
Import the effect
you wish to use:
import green.thisfieldwas.embracingnondeterminism.data.NonEmptyList
In order to use NonEmptyList
as a Functor
import both Functor
and NonEmptyList
's instances:
import green.thisfieldwas.embracingnondeterminism.data.{Functor, NonEmptyList}
import green.thisfieldwas.embracingnondeterminism.data.NonEmptyList.Instances._
Functor[NonEmptyList].map(NonEmptyList(1, 2, 3))(x => x * 2) // => NonEmptyList(1, 4, 6)
If you wish to use object-oriented syntax, import Functor
s extension methods:
import green.thisfieldwas.embracingnondeterminism.data.{Functor, NonEmptyList}
import green.thisfieldwas.embracingnondeterminism.data.NonEmptyList.Instances._
import green.thisfieldwas.embracingnondeterminism.data.Functor.Syntax._
NonEmptyList(1, 2, 3).map(x => x * 2) // => NonEmptyList(1, 4, 6)
Using sbt console
Import all project definitions by loading the following script after launching the console:
scala> :load console/imports.scala
This will pull all classes and implicits into scope so that you can work with them directly in the console and experiment with them yourself.