No Haskell, o functor da classe de tipos Functor é definido da seguinte forma (consulte, por exemplo, wiki do Haskell ):
class Functor (f :: * -> *) where
fmap :: (a -> b) -> f a -> f b
Tanto quanto eu entendo (por favor me corrijam se eu estiver errado), tal functor só pode ter como alvo categoria uma categoria construída usando um construtor de tipo, por exemplo []
, Maybe
, etc. Por outro lado, pode-se pensar em functors com qualquer categoria como alvo de um functor, por exemplo, a categoria de todos os tipos de Haskell. Por exemplo, Int
poderia ser um objeto na categoria de destino de um functor, não apenas Maybe Int
ou [Int]
.
Qual é a motivação para essa restrição nos funcionadores Haskell?
f
direita? E no seu cenário,f
deve ser como uma função Haskell normal e mapear tipos para tipos. Em Haskell, as únicas coisas que podem ter esse tipo* -> *
são construtores de tipo. Famílias tipográficas são mais gerais, mas devem sempre ser totalmente aplicadoRespostas:
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:
e
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çãofmap
(cabe ao compilador Haskell classificar a quefmap
estamos nos referindo em qualquer expressão). Assim, não podemos dizer queList
é um functor; apenas a combinação deList
efmap
é um functor. Ainda assim, as pessoas abusam da notação; os programadores chamamList
um 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
List
como exemplo: temos um construtor de tiposList : Type -> Type
e uma funçãofmap: (a -> b) -> (List a -> List b)
que juntos formam um functor. THá um último ponto a esclarecer. A escrita
List int
nã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,
Int
ouString
. 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 tiposid : * -> *
que mapeia todos os tipos para si. Por exemplo,id int
avalia comoint
.Além disso, pode-se até criar functores constantes , que mapeiam todos os tipos para um único tipo. Por exemplo, o functor
ToInt : * -> *
, ondeToInt a = int
para todos os tiposa
, e mapeia todos os morfismos para a função de identidade inteira:fmap f = \x -> x
fonte
f a
, ondef
é, até onde eu sei, um construtor de tipos. Pelo que me lembro da teoria das categorias, deve ser algum tipo de representação canônica (objeto inicial em uma categoria de categorias? Talvez esteja usando mal a terminologia.) De qualquer forma, vou ler sua resposta com atenção. Muito Obrigado.[]
e:
. Eu quis dizer isso por representação canônica.(_, int)
que leva um tipoa
para o tipo de produto(a, int)
e uma funçãof : 'a -> 'b
parag : 'a * int -> 'a * int
não é indutivo.f : 'a -> 'b
parag : 'a * int -> 'b * int
?"