Functor (functional programming)

From English Wikipedia @ Freddythechick
File:Tree as a functor.svg
Applying <syntaxhighlight lang="text" class="" style="" inline="1">fmap (+1)</syntaxhighlight> to a binary tree of integers increments each integer in the tree by one.

In functional programming, a functor is a design pattern inspired by the definition from category theory that allows one to apply a function to values inside a generic type without changing the structure of the generic type. In Haskell this idea can be captured in a type class:

<syntaxhighlight lang="haskell"> class Functor f where

 fmap :: (a -> b) -> f a -> f b

</syntaxhighlight>

This declaration says that any type of Functor must support a method fmap, which maps a function over the element(s) of the Functor.

Functors in Haskell should also obey functor laws,[1] which state that the mapping operation preserves the identity function and composition of functions:

<syntaxhighlight lang="haskell"> fmap id = id fmap (g . h) = (fmap g) . (fmap h) </syntaxhighlight>

(where . stands for function composition).

In Scala a trait can be used:

<syntaxhighlight lang="scala"> trait Functor[F[_]] {

 def map[A,B](a: F[A])(f: A => B): F[B]

}

</syntaxhighlight>

Functors form a base for more complex abstractions like Applicative Functor, Monad, and Comonad, all of which build atop a canonical functor structure. Functors are useful in modeling functional effects by values of parameterized data types. Modifiable computations are modeled by allowing a pure function to be applied to values of the "inner" type, thus creating the new overall value which represents the modified computation (which might yet to be run).

Examples

In Haskell, lists are a simple example of a functor. We may implement <syntaxhighlight lang="text" class="" style="" inline="1">fmap</syntaxhighlight> as

<syntaxhighlight lang="haskell"> fmap f [] = [] fmap f (x:xs) = (f x) : fmap f xs </syntaxhighlight>

A binary tree may similarly be described as a functor:

<syntaxhighlight lang="haskell"> data Tree a = Leaf | Node a (Tree a) (Tree a) instance Functor Tree where

  fmap f Leaf         = Leaf
  fmap f (Node x l r) = Node (f x) (fmap f l) (fmap f r)

</syntaxhighlight>

If we have a binary tree <syntaxhighlight lang="text" class="" style="" inline="1">tr :: Tree a</syntaxhighlight> and a function <syntaxhighlight lang="text" class="" style="" inline="1">f :: a -> b</syntaxhighlight>, the function <syntaxhighlight lang="text" class="" style="" inline="1">fmap f tr</syntaxhighlight> will apply <syntaxhighlight lang="text" class="" style="" inline="1">f</syntaxhighlight> to every element of <syntaxhighlight lang="text" class="" style="" inline="1">tr</syntaxhighlight>. For example, if <syntaxhighlight lang="text" class="" style="" inline="1">a</syntaxhighlight> is <syntaxhighlight lang="text" class="" style="" inline="1">Int</syntaxhighlight>, adding 1 to each element of <syntaxhighlight lang="text" class="" style="" inline="1">tr</syntaxhighlight> can be expressed as <syntaxhighlight lang="text" class="" style="" inline="1">fmap (+ 1) tr</syntaxhighlight>.[2]

See also

References

  1. ^ Yorgey, Brent. "Functor > Laws". HaskellWiki. Retrieved 17 June 2023.
  2. ^ "Functors". Functional Pearls. University of Maryland. Retrieved 12 December 2022.

External links