<commit_before>---
layout: docs
title: Parallelism
---

# Parallelism and non-determinism

Freestyle supports building programs that support both sequential and parallel computations.

```
TODO Code example
```

# Rationale

One of the biggest issue with architectures based on Free monads is that by default `cats.free.Free` does not support parallelism since your actions as described as a series of
sequential monadic steps. Each computation step is built with `Free#flatMap` and evaluated via `Free#foldMap`. 
This is not an issue when your operations produce and output value and that value is used as input in the next step in the monadic sequence but it's rather hard
to express computations that may be performed in parallel.

# Hinting Parallelization

As you may have noticed by now Freestyle uses a type alias as return type of your operations called `FreeS`. 
FreeS is an alias for a Free monad that represents a sequential fragment of potentially multiple parallel steps.

```
type FreeS[F[_], A] = Free[FreeApplicative[F, ?], A]
```

We use `FreeS.Par` an alias for `FreeAplicative` to denote functions that represents a potential parallel step.

Independent operations that can be executed potentially in parallel may be placed inside `@free` algebras as abstract definitions like in the example below.

```tut:silent
@free trait Validation[F[_]] {
	def minSize(n: Int): FreeS.Par[F, Boolean]
	def hasNumber: FreeS.Par[F, Boolean]
}
```

# Parallel interpretation

Interpreters for operations that are executed in parallel should target a type for which there is a monad instance that supports parallelism.
Freestyle ships with ready to use instances for `scala.concurrent.Future` and contains extension modules for [`monix.eval.Task`]() and [`akka actors`]()

To enable the instances and support parallelism you need to

```tut:silent
import io.freestyle.nondeterminism._
```

The code below ilustrate an interpreter that will allow parallel executions thanks to the unsafe start of a by name value applied to `scala.concurrent.Future#apply`

```tut:silent
import cats.data.Kleisli
import cats.implicits._
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

import io.freestyle.implicits._

type ParValidator[A] = Kleisli[Future, String, A]

implicit val interpreter = new Validation.Interpreter[ParValidator] {
	override def minSizeImpl(n: Int): ParValidator[Boolean] =
		Kleisli(s => Future(s.size >= n))

	override def hasNumberImpl: ParValidator[Boolean] =
		Kleisli(s => Future(s.exists(c => "0123456789".contains(c))))
}

val validation = Validation[Validation.T]
import validation._

val parValidation = (minSize(3) |@| hasNumber).map(_ :: _ :: Nil)

val validator = parValidation.exec[ParValidator]<commit_msg>Docs fixes<commit_after>---
layout: docs
title: Parallelism
---

# Parallelism and non-determinism

Freestyle supports building programs that support both sequential and parallel computations.

```
TODO Code example
```

# Rationale

One of the biggest issue with architectures based on Free monads is that by default `cats.free.Free` does not support parallelism since your actions as described as a series of
sequential monadic steps. Each computation step is built with `Free#flatMap` and evaluated via `Free#foldMap`. 
This is not an issue when your operations produce and output value and that value is used as input in the next step in the monadic sequence but it's rather hard
to express computations that may be performed in parallel.

# Hinting Parallelization

As you may have noticed by now Freestyle uses a type alias as return type of your operations called `FreeS`. 
FreeS is an alias for a Free monad that represents a sequential fragment of potentially multiple parallel steps.

```
type FreeS[F[_], A] = Free[FreeApplicative[F, ?], A]
```

We use `FreeS.Par` an alias for `FreeAplicative` to denote functions that represents a potential parallel step.

Independent operations that can be executed potentially in parallel may be placed inside `@free` algebras as abstract definitions like in the example below.

```tut:silent
@free trait Validation[F[_]] {
	def minSize(n: Int): FreeS.Par[F, Boolean]
	def hasNumber: FreeS.Par[F, Boolean]
}
```

# Parallel interpretation

Interpreters for operations that are executed in parallel should target a type for which there is a monad instance that supports parallelism.
Freestyle ships with ready to use instances for `scala.concurrent.Future` and contains extension modules for [`monix.eval.Task`]() and [`akka actors`]()

To enable these instances and support parallelism you need to explicitly import:

```tut:silent
import io.freestyle.nondeterminism._
```

The code below ilustrate an interpreter that will allow parallel executions thanks to the unsafe nature of `scala.concurrent.Future#apply` which runs immediately.

```tut:silent
import cats.data.Kleisli
import cats.implicits._
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

import io.freestyle.implicits._

type ParValidator[A] = Kleisli[Future, String, A]

implicit val interpreter = new Validation.Interpreter[ParValidator] {
	override def minSizeImpl(n: Int): ParValidator[Boolean] =
		Kleisli(s => Future(s.size >= n))

	override def hasNumberImpl: ParValidator[Boolean] =
		Kleisli(s => Future(s.exists(c => "0123456789".contains(c))))
}

val validation = Validation[Validation.T]
import validation._

val parValidation = (minSize(3) |@| hasNumber).map(_ :: _ :: Nil)

val validator = parValidation.exec[ParValidator]
{'fraction_non_alphanumeric': 0.0800711743772242, 'fraction_numerical': 0.003914590747330961, 'mean_word_length': 5.204194260485651, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1663799', 'n_tokens_mistral': 1614, 'n_tokens_neox': 1530, 'n_words': 665}