Não há nenhuma restrição! Quando comecei a aprender a base teórica da categoria para construtores de tipos, esse mesmo ponto também me confundiu. Nós vamos chegar a isso. Mas primeiro, deixe-me esclarecer alguma confusão. Estas duas citações:
esse functor pode ter apenas como categoria de destino uma categoria construída usando um construtor de tipo
e
pode-se pensar em functores tendo qualquer categoria como alvo de um functor, por exemplo, a categoria de todos os tipos de Haskell
mostre que você está entendendo mal o que é um functor (ou pelo menos está usando mal a terminologia).
Functors não constroem categorias. Um functor é um mapeamento entre categorias. Os fundores trazem objetos e morfismos (tipos e funções) na categoria de origem para objetos e morfismos na categoria de destino.
Observe que isso significa que um functor é realmente um par de mapeamentos: um mapeamento nos objetos F_obj e um mapeamento nos morfismos F_morph . Em Haskell, a parte do objeto F_obj do functor é o nome do construtor de tipos (por exemplo List), enquanto a parte do morfismo é a função fmap(cabe ao compilador Haskell classificar a que fmapestamos nos referindo em qualquer expressão). Assim, não podemos dizer que Listé um functor; apenas a combinação de Liste fmapé um functor. Ainda assim, as pessoas abusam da notação; os programadores chamam Listum functor, enquanto os teóricos da categoria usam o mesmo símbolo para se referir às duas partes do functor.
Além disso, na programação, quase todos os functores são endofuncionadores , ou seja, a categoria de origem e destino são os mesmos - a categoria de todos os tipos em nossa linguagem. Vamos chamar essa categoria de Tipo . Um endofuncor F no tipo mapeia um tipo T para outro tipo FT e uma função T -> S para outra função FT -> FS . É claro que esse mapeamento deve obedecer às leis do functor.
Usando Listcomo exemplo: temos um construtor de tipos List : Type -> Typee uma função fmap: (a -> b) -> (List a -> List b)que juntos formam um functor. T
Há um último ponto a esclarecer. A escrita List intnão cria um novo tipo de lista de números inteiros. Este tipo já existia . Foi um objeto em nossa categoria Tipo . List Inté simplesmente uma maneira de se referir a ele.
Agora, você está se perguntando por que um functor não pode mapear um tipo para, digamos, Intou String. Mas pode! Basta usar o functor de identidade. Para qualquer categoria C , o functor de identidade mapeia todos os objetos para si e o morfismo para si. É fácil verificar se esse mapeamento satisfaz as leis do functor. Em Haskell, esse seria um construtor de tipos id : * -> *que mapeia todos os tipos para si. Por exemplo, id intavalia como int.
Além disso, pode-se até criar functores constantes , que mapeiam todos os tipos para um único tipo. Por exemplo, o functor ToInt : * -> *, onde ToInt a = intpara todos os tipos a, e mapeia todos os morfismos para a função de identidade inteira: fmap f = \x -> x