Transformação Natural

Esse post é baseado no livro Teoria das Categorias para Programadores, de Bartosz Milewski.

1 Transformação Natural

Dados dois Functors \(F, G : C \rightarrow D\) da categoria \(C\) para a categoria \(D\), chamamos o morfismo \(\alpha_a :: F a \rightarrow G a\) uma Transformação Natural entre \(F\) e \(G\):

alpha :: F a -> G a

Tal transformação deve permitir o quadrado comutativo:

Isso permite criarmos a função g :: F a -> G b de duas maneiras:

-- G f . alpha = alpha . F f
g = fmap f . alpha = alpha . fmap f

A comutatividade implica que ao aplicar a primeira ou a segunda definição de g para um valor de a, o resultado deve ser exatamente o mesmo valor de b. Por exemplo, considere a seguinte transformação natural de lista para o tipo Maybe:

safeHead :: [a] -> Maybe a
safeHead []     = Nothing
safeHead (x:xs) = Just x

Para ser uma transformação natural devemos garantir que fmap f . safeHead = safeHead . fmap f:

fmap f . safeHead [] = safeHead . fmap f []
fmap f Nothing = safeHead []
Nothing = Nothing

fmap f . safeHead (x:xs) = safeHead . fmap f (x:xs)
fmap f . Just x = safeHead . f x
Just (f x) = Just (f x)

Um outro exemplo é a função length:

length :: [a] -> Int

podemos pensar nela como uma transformação natural que converte uma lista para um Functor Const Int a:

length :: [a] -> Const Int a

Podemos verificar que é uma transformação natural pois pela definição de fmap para lista, o tamanho da lista permanece o mesmo. Da mesma forma a função fmap aplicado em um valor Const retorna o próprio valor.

2 Referências

https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/