En programación funcional , un funtor es un patrón de diseño inspirado en la definición de la teoría de categorías que permite aplicar una función a valores dentro de un tipo genérico sin cambiar la estructura del tipo genérico. En Haskell, esta idea se puede plasmar en una clase de tipo :
clase Functor f donde fmap :: ( a -> b ) -> f a -> f b
Esta declaración dice que cualquier tipo de Functor debe soportar un método fmap
, que mapea una función sobre los elementos del Functor.
Los funtores en Haskell también deben obedecer las leyes de funtores , [1] que establecen que la operación de mapeo preserva la función identidad y la composición de funciones:
fmap id = id fmap ( g . h ) = ( fmap g ) . ( fmap h )
(donde .
representa la composición de funciones ).
En Scala se puede utilizar un rasgo :
rasgo Functor [ F [ _ ]] { def mapa [ A , B ]( a : F [ A ])( f : A => B ): F [ B ] }
Los funtores forman una base para abstracciones más complejas como Applicative Functor , Monad y Comonad , todas las cuales se construyen sobre una estructura de funtor canónico. Los funtores son útiles para modelar efectos funcionales mediante valores de tipos de datos parametrizados. Los cálculos modificables se modelan permitiendo que se aplique una función pura a valores del tipo "interno", creando así el nuevo valor general que representa el cálculo modificado (que aún podría estar por ejecutarse).
En Haskell, las listas son un ejemplo simple de un funtor. Podemos implementarlo fmap
como
fmap f [] = [] fmap f ( x : xs ) = ( f x ) : fmap f xs
Un árbol binario también puede describirse como un funtor:
datos Árbol a = Hoja | Nodo a ( Árbol a ) ( Árbol a ) instancia Functor Árbol donde fmap f Hoja = Hoja fmap f ( Nodo x l r ) = Nodo ( f x ) ( fmap f l ) ( fmap f r )
Si tenemos un árbol binario tr :: Tree a
y una función f :: a -> b
, la función fmap f tr
se aplicará f
a cada elemento de tr
. Por ejemplo, si a
es Int
, sumar 1 a cada elemento de tr
se puede expresar como fmap (+ 1) tr
. [2]