# Key Terminology

Read this entire walkthrough.

{% embed url="<https://dev.to/gcanti/getting-started-with-fp-ts-setoid-39f3>" %}

#### Type / Category

A type is a mathematical concept referring to a category, in lay-speak. The more formal idea of a category is better defined as:

* Consistent groupings of **objects**
* Certain transformations between those groupings, known as **morphisms**

An **object** may also be a **morhphism**, this is where **Functors** come in.

#### Function

Denoted as `f(a)` Defines a mapping between types, taking the form:

`f: a -> b`

Where `a` is the input type and `b` is the output type.

#### Algebra

An algebra is a family of functions with the signature `f: a -> a` for a given category `a`.

#### Type Constructor

A [type constructor](https://en.wikipedia.org/wiki/Type_constructor) is an `n`-ary type operator taking as argument zero or more types, and returning another type. It has the type of signature:

`a -> F<a>`

Often used to model side-effects in a program. Examples include:

`List<a>` `Option<a>` `Task<a>`

#### Catamorphism

A catamorphism is a generalised morphism concept that performs an operation known as `fold` or `reduce`.

The name comes from the Greek 'κατα-' meaning "downward or according to". A useful mnemonic is to think of a catastrophe destroying something.&#x20;

{% embed url="<https://wiki.haskell.org/Catamorphisms>" %}

#### Functor

A type constructor is classed as a Functor if the `lift` operation can be defined for it. To avoid further confusion let it be clear that `lift`, `map` and `fmap` can be conceptually considered equivalent.

Say we have:

`f: a -> F<b>`

`g: b -> c`

How can we compose `f` and `g` together? `lift`ing is the process of taking `b -> c` and creating `F<b> -> F<c>`.&#x20;

Which in turn lets us compose `a -> F<b>` and `F<b> -> F<c>` trivially as `a -> F<b> -> F<c>` and ultimately `a -> F<c>`.

A more complete way to define a Functor is that it is made up of two aspects:

* `A type constructor F:` a **mapping between objects** that associates to each object `X` in *a* an object in *b*
* `A function lift:` a **mapping between morphisms** that associates to each morphism in *c* a morphism in *d*

Examples:

```fsharp
let lift (g: b -> c) (fb: List<b>) = fb |> List.map g
```

```typescript
function lift<B, C>(g: (b: B) => C): (fb: Array<B>) => Array<C> {
  return fb => fb.map(g)
}

function lift<B, C>(g: (b: B) => C): (fb: Option<B>) => Option<C> {
  return fb => (isNone(fb) ? none : some(g(fb.value)))
}

function lift<B, C>(g: (b: B) => C): (fb: Task<B>) => Task<C> {
  return fb => () => fb().then(g)
}
```

{% embed url="<https://dev.to/gcanti/getting-started-with-fp-ts-functor-36ek>" %}

#### Endofunctors

An endofunctor is a functor mapping to and from the same category, `F: C -> C.`

The simplest example of an endofunctor is `id` which has the signature `a -> a`. We can define the identity endofunctor as:

```fsharp
module Identity =
    // ('a -> 'b) -> Identity<'a> -> Identity<'b>
    let map f (Identity x) = Identity (f x)
```

Similarly, the `Maybe` endofunctor has the form:

```haskell
instance Functor Maybe where
  fmap f Nothing = Nothing
  fmap f (Just x) = Just (f x)
```

If unclear, the defining property that makes a functor an endofunctor above is that `fmap` always preserves the category, which is not necessarily true for a functor.

{% embed url="<https://blog.ploeh.dk/2018/09/03/the-identity-functor/>" %}

#### F-Algebra

Building on the base idea of an algebra, an F-Algebra is composed of three things:

* An endofunctor `F`
* An object `a` that is "inside" the endofunctor as the carried type
* A morphism of the form `F<a> -> a`, often called the evaluation function or the structure map

Once again, `Maybe` is an example of an F-Algebra.

```haskell
data MaybeF a c = NothingF | JustF a deriving (Show, Eq, Read)
 
instance Functor (MaybeF a) where
  fmap _  NothingF = NothingF
  fmap _ (JustF x) = JustF x
```

{% embed url="<https://blog.ploeh.dk/2019/05/20/maybe-catamorphism/>" %}

#### Semigroup

A semigroup is a pair `(A, *)` in which `A` is a non-empty set and `*` is a binary **associative** operation on `A`, i.e. a function that takes two elements of `A` as input and returns an element of `A` as output.&#x20;

Effectively, this means that the `concat` morphism can be defined.

```typescript
interface Semigroup<A> {
  concat: (x: A, y: A) => A
}

const semigroupProduct: Semigroup<number> = {
  concat: (x, y) => x * y
}

const semigroupSum: Semigroup<number> = {
  concat: (x, y) => x + y
}

const semigroupString: Semigroup<string> = {
  concat: (x, y) => x + y
}
```

#### Applicative Functors

A Functor is classed as Applicative if the `apply` morphism can be defined for it, these are also simply known as Applicatives for short. In practical terms this property allows us to handle `n-ary` Functors rather than just `unary`.

`apply` as an operation on the functor instance `F` is able to **unpack** the value `F<(c: C) => D>` to a function `(fc: F<C>) => F<D>`.

Examples

`F = Array`

```typescript
import { flatten } from 'fp-ts/lib/Array'

const applicativeArray = {
  map: <A, B>(fa: Array<A>, f: (a: A) => B): Array<B> => fa.map(f),
  of: <A>(a: A): Array<A> => [a],
  ap: <A, B>(fab: Array<(a: A) => B>, fa: Array<A>): Array<B> =>
    flatten(fab.map(f => fa.map(f))) // flatten prevents [['a']] style output
}
```

`F = Option`

```typescript
import { Option, some, none, isNone } from 'fp-ts/lib/Option'

const applicativeOption = {
  map: <A, B>(fa: Option<A>, f: (a: A) => B): Option<B> =>
    isNone(fa) ? none : some(f(fa.value)),
  of: <A>(a: A): Option<A> => some(a),
  ap: <A, B>(fab: Option<(a: A) => B>, fa: Option<A>): Option<B> =>
    isNone(fab) ? none : applicativeOption.map(fa, fab.value)
}
```

`F = Task`

```typescript
import { Task } from 'fp-ts/lib/Task'

const applicativeTask = {
  map: <A, B>(fa: Task<A>, f: (a: A) => B): Task<B> => () => fa().then(f),
  of: <A>(a: A): Task<A> => () => Promise.resolve(a),
  ap: <A, B>(fab: Task<(a: A) => B>, fa: Task<A>): Task<B> => () =>
    Promise.all([fab(), fa()]).then(([f, a]) => f(a))
}
```

{% embed url="<https://dev.to/gcanti/getting-started-with-fp-ts-applicative-1kb3>" %}

#### Monoid

A `Monoid` is any `Semigroup` that happens to have a special value which is "neutral" with respect to `concat`. Do note, not all Semigroups are Monoids.

```typescript
import { Semigroup } from 'fp-ts/lib/Semigroup'

interface Monoid<A> extends Semigroup<A> {
  readonly empty: A
}
```

The following laws must hold

* **Right identity**: `concat(x, empty) = x`, for all `x` in `A`
* **Left identity**: `concat(empty, x) = x`, for all `x` in `A`

```typescript
/** number `Monoid` under addition */
const monoidSum: Monoid<number> = {
  concat: (x, y) => x + y,
  empty: 0
}

/** number `Monoid` under multiplication */
const monoidProduct: Monoid<number> = {
  concat: (x, y) => x * y,
  empty: 1
}

const monoidString: Monoid<string> = {
  concat: (x, y) => x + y,
  empty: ''
}

/** boolean monoid under conjunction */
const monoidAll: Monoid<boolean> = {
  concat: (x, y) => x && y,
  empty: true
}

/** boolean monoid under disjunction */
const monoidAny: Monoid<boolean> = {
  concat: (x, y) => x || y,
  empty: false
}
```

#### **Non-Monoidal Semigroup**

A trivial example of a semigroup for which `empty` cannot be defined to satisfy the right and left identity laws.

```typescript
const semigroupSpace: Semigroup<string> = {
  concat: (x, y) => x + ' ' + y
}
```

{% embed url="<https://dev.to/gcanti/getting-started-with-fp-ts-monoid-ja0>" %}

#### Monad

A Monad is simply a Monoid in the category of Endofunctors 🙃.

What this practically means is that we can define the operations:

* `of: a -> M<a>`
* `map: M<a> -> M<b>`
* `get: M<a> -> a`
* `concat: M<a> -> M<a> -> M<a>`
* `flatten: M<M<a>> -> M<a>`
* `flatMap: (a -> M<b>) -> (M<a> -> M<b>)`

####

####

**Pending questions to directly address**:

* how does `filter` fit in?
* define transducers
* draw a diagram of related terms
* how does a catamorphism interact with the definitions of semigroup, monoid and monad?
* what is the **common** set of useful morphisms?
  * map
  * get
  * concat
  * bind / chain / of(?)
  * apply
  * fold
  * unfold


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://notes.bf.wtf/programming/functional-programming/key-terminology.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
