Um foo livre passa a ser a coisa mais simples que satisfaz todas as leis 'foo'. Isto é, satisfaz exatamente as leis necessárias para ser um foo e nada extra.
Um functor esquecido é aquele que "esquece" parte da estrutura à medida que passa de uma categoria para outra.
Dado functors F : D -> C
, e G : C -> D
, dizemos F -| G
, F
é deixado adjacente a G
, ou G
é adjacente a todo momento em F
que todos a, b: F a -> b
é isomórfico para a -> G b
, onde as setas vêm das categorias apropriadas.
Formalmente, um functor livre fica adjacente a um functor esquecido.
O Monóide Livre
Vamos começar com um exemplo mais simples, o monóide livre.
Dê uma monoid, que é definida por um conjunto transportador T
, uma função binário para esmagar um par de elementos juntos f :: T → T → T
, e uma unit :: T
, de modo que você tem uma lei associativa, e uma lei de identidade: f(unit,x) = x = f(x,unit)
.
Você pode fazer um functor U
da categoria de monoids (onde flechas são homomorphisms monoid, isto é, garantir que eles mapear unit
a unit
do outro monoid, e que você pode compor antes ou após o mapeamento para o outro monoid sem alterar o significado) à categoria de conjuntos (onde as setas são apenas setas funcionais) que 'esquecem' da operação e unit
, e apenas fornecem o conjunto da transportadora.
Em seguida, você pode definir um functor F
da categoria de conjuntos para a categoria de monoides que fica adjacente a esse functor. Esse functor é o functor que mapeia um conjunto a
para o monóide [a]
, onde unit = []
, e mappend = (++)
.
Então, para revisar nosso exemplo até agora, em pseudo-Haskell:
U : Mon → Set -- is our forgetful functor
U (a,mappend,mempty) = a
F : Set → Mon -- is our free functor
F a = ([a],(++),[])
Então, para mostrar F
é gratuito, precisamos demonstrar que ele fica adjacente a U
um functor esquecido, ou seja, como mencionamos acima, precisamos mostrar que
F a → b
é isomórfico para a → U b
Agora, lembre-se de que o alvo de F
está na categoria Mon
de monóides, onde as setas são homomorfismos monóides; portanto, precisamos mostrar que um homomorfismo monóide de [a] → b
pode ser descrito precisamente por uma função de a → b
.
Em Haskell, chamamos o lado disso que vive em Set
(er, Hask
a categoria de tipos de Haskell que pretendemos ser Set), just foldMap
, que quando especializada de Data.Foldable
para Lists tem tipo Monoid m => (a → m) → [a] → m
.
Há conseqüências que se seguem, sendo uma adjunção. Notavelmente, se você esquecer, construa gratuitamente, e esqueça novamente, é como você esqueceu uma vez, e podemos usar isso para criar a junção monádica. desde UFUF
~ U(FUF)
~ UF
, e podemos passar o homomorfismo monóide de identidade de [a]
para [a]
o isomorfismo que define nossa adjunção, entender que um isomorfismo de lista [a] → [a]
é uma função do tipo a -> [a]
, e isso é apenas um retorno para listas.
Você pode compor tudo isso mais diretamente, descrevendo uma lista nestes termos com:
newtype List a = List (forall b. Monoid b => (a -> b) -> b)
The Free Monad
Então, o que é uma Mônada Livre ?
Bem, fazemos o mesmo que fizemos antes, começamos com um esquecido functor U da categoria de mônadas, onde as flechas são mônadas homomorfismos, até uma categoria de endofuncionadores, onde as flechas são transformações naturais, e procuramos um functor que fica ao lado para isso.
Então, como isso se relaciona com a noção de mônada livre, como costuma ser usada?
Saber que algo é uma mônada livre Free f
, diz a você que fornecer uma homônima de mônada Free f -> m
é a mesma coisa (isomórfica a) que fornecer uma transformação natural (de um homomorfismo de functor) f -> m
. Lembre-se de que F a -> b
deve ser isomórfico para a -> U b
que F seja deixado adjacente a U. U aqui mapeou mônadas para functores.
F é pelo menos isomorfo ao Free
tipo que eu uso no meu free
pacote sobre hackage.
Também podemos construí-lo em analogia mais rigorosa ao código acima para a lista livre, definindo
class Algebra f x where
phi :: f x -> x
newtype Free f a = Free (forall x. Algebra f x => (a -> x) -> x)
Comonadas Cofree
Podemos construir algo semelhante, observando o anexo correto de um functor esquecido, assumindo que ele existe. Um functor co-livre é simplesmente / diretamente adjunto / a um functor esquecido e, por simetria, saber que algo é uma comonada livre é o mesmo que saber que dar homomorfismo a uma comonada w -> Cofree f
é o mesmo que dar uma transformação natural w -> f
.