Você está na página 1de 87

FUNES SOBRECARREGADAS COMO OBJETOS DE PRIMEIRA CLASSE

ELTON MXIMO CARDOSO

FUNES SOBRECARREGADAS COMO OBJETOS DE PRIMEIRA CLASSE


Dissertao apresentada ao Programa de Ps-Graduao em Cincia da Computao do Instituto de Cincias Exatas da Universidade Federal de Minas Gerais como requisito parcial para a obteno do grau de Mestre em Cincia da Computao.

Orientador: Carlos Camaro de Figueiredo Co-Orientador: Luclia Camaro de Figueiredo

Belo Horizonte Janeiro de 2011

2011, Elton Mximo Cardoso. Todos os direitos reservados.

Cardoso, Elton Mximo C268f Funes sobrecarregadas como objetos de primeira classe / Elton Mximo Cardoso. Belo Horizonte, 2011 xii, 67 f. : il. ; 29cm Dissertao (mestrado) Universidade Federal de Minas Gerais Orientador: Carlos Camaro de Figueiredo Co-Orientador: Luclia Camaro de Figueiredo 1. Computao. 2. Tese. 3. Linguagem de Programao (computadores) - Tese. I. Orientador II. Co-Orientador. III. Ttulo. CDU 519.6*33 (043)

Agradecimentos
Ao Departamento de Computao da Universidade Federal de Minas Gerais, pelas instalaes, infraestrutura e apoio para o desenvolvimento deste trabalho. Aos professores Carlos Camaro Figueiredo e Luclia Camaro Figueiredo, respectivamente orientador e coorientador deste trabalho, pelo constante apoio, estmulo e pelo rigor nas inmeras correes que se zeram necessrias ao longo do trabalho. Aos professores das disciplinas que cursei, pelas valiosas lies. Agradeo aos meus pais pela compreenso, e pelo amparo durante o tempo em que esse trabalho foi realizado. Ao meu irmo, por seus bons conselhos e por ser sempre to prestativo. Agradeo ao amigo Rodrigo Geraldo Ribeiro por ter cedido o cdigo utilizado como base para implementao descrita neste trabalho e tambm pela companhia e pelos bons temas de discusso durante o caf. Aos amigos Leonardo V. S. R., Srgio M. D. e Henrique L. B. pelo companheirismo. Aos amigos Euler H. M. e Pedro C. G. pela assistncia em Linux nas horas de desespero.

vii

Por natureza, o egosmo ilimitado: o homem quer conservar a sua existncia utilizando qualquer meio ao seu alcance, quer car totalmente livre das dores que tambm incluem a falta e a privao, quer a maior quantidade possvel de bem-estar e todo o prazer de que for capaz, e chega at mesmo a tentar desenvolver em si mesmo, quando possvel, novas capacidades de deleite. Tudo o que se ope ao mpeto do seu egosmo provoca o seu mau humor, a sua ira e o seu dio: ele tentar aniquil-lo como a um inimigo. Quer possivelmente desfrutar de tudo e possuir tudo; mas, como isso impossvel, quer, pelo menos, dominar tudo: "Tudo para mim e nada para os outros" o seu lema. O egosmo gigantesco: ele rege o mundo. (Arthur Schopenhauer - A Arte de Insultar ) ix

Resumo
O uso de polimorsmo em linguagens de programao constitui um importante recurso para reuso de cdigo e para clareza e conciso de programas. A base para implementao de polimorsmo em linguagens de programao modernas o sistema de tipos de Hindley-Milner (HM) e uma extenso bastante til desse sistema a possibilidade de denio de smbolos sobrecarregados (com tipo polimrco restrito). No sistema HM a inferncia de tipos relativamente simples, em razo de sua restrio de que parmetros de funes devem ter tipo monomrco. Esse requerimento pode entretanto ser um inconveniente em diversas aplicaes. Este trabalho prope uma extenso ao sistema de tipos de Hindley-Milner + sobrecarga, a qual possibilita a denio de funes com parmetros de tipo polimrco, mediante anotao explcita do tipo de tais funes pelo programador, sendo esses tipos especicados na forma de tipos interseo. No sistema proposto, funes com parmetros polimrcos podem tanto ser aplicadas a argumentos de tipo polimrco paramtrico (como em sistemas de polimorsmo de rank superior), como a argumentos de tipo polimrco restrito, promovendo valores sobrecarregados a objetos de primeira classe .

xi

Abstract
The use of polymorphic abstractions in programmming languages constitutes an important tool for code reuse and for program clarity and conciseness. The basis of most modern languages for the exploitation of polymorphism is Hindley-Milners type system, which has achieved such success due in great part to the relative simplicity of its type inference mechanism. This simplicity is obtained, however, by imposing some restrictions. A major restriction is the (so-called) no polymorphic abstraction: function parameters must have a monomorphic type (in other words, parameters cannot be used with distinct types inside the functions body). There has been much work on extensions to overcome this restriction, involving so-called higher rank (also called rank-n) type systems, which allow arguments of polymorphic type. This work follows such vein, but is distinguished from all previous related work as follows. Intersection types are used to allow parameters to be used polymorphically inside a functions denition (the type of such polymorphic parameters must be explicitly annotated); this allows such function to receive arguments not only of polymorphic type may also of constrained polymorphic type (i.e. arguments involving the use of overloaded symbols). This promotes overloaded values to rst-class.

xiii

Lista de Figuras
2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.1 3.2 3.3 3.4 3.5 3.6 4.1 4.2 4.3 4.4 4.5 Sintaxe de tipos . . . . . . . . . . . . . . Sintaxe do lambda-calculus . . . . . . . Sistema de Tipos HM . . . . . . . . . . . rvore de derivao de tipo . . . . . . . Sistema de tipos HM dirigido por sintaxe Inferncia de tipos para HM . . . . . . . . Semntica do sistema HM . . . . . . . . . Sintaxe da linguagem do sistema F . . . Sistema F . . . . . . . . . . . . . . . . . Sintaxe da linguagem do sistema CTH . Provabilidade de predicados de classe . Propriedades de P |= Q . . . . . . . . Sistema de tipos CTH . . . . . . . . . . Restries de P atingveis a partir de V Inferncia de tipos para CTH . . . . . . Sintaxe da linguagem do sistema CTi . Sistema de tipos CTi . . . . . . . . . . Inferncia de tipos para CTi . . . . . . Inferncia de tipo da aplicao, dirigida Inferncia de tipo da aplicao, dirigida . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 11 13 14 16 18 22 24 24 32 33 34 36 37 38 46 48 51 53 53

. . . . . . .

. . . . . . . . . pelo pelo

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . tipo da funo . . tipo do argumento

xv

Lista de Tabelas

xvii

Sumrio
Agradecimentos Resumo Abstract Lista de Figuras Lista de Tabelas 1 Introduo 1.1 Organizao . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . vii xi xiii xv xvii 1 7 9 9 12 13 15 17 21 23 23 25 26 29 30 31 35 37

2 Polimorsmo Paramtrico 2.1 2.2 Conceitos Bsicos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Polimorsmo de Rank -1 . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 2.2.2 2.2.3 2.2.4 2.3 2.3.1 2.3.2 2.4 Sistema de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . Sistema de Tipos Dirigido por Sintaxe . . . . . . . . . . . . . . Inferncia de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . Semntica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Sistema F . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Estendendo HM com polimorsmo de rank-n . . . . . . . . . . .

Polimorsmo de Rank Superior . . . . . . . . . . . . . . . . . . . . . .

Concluso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

3 Polimorsmo Restrito: Sobrecarga 3.1 3.2 3.3 3.4 Classes de tipos em Haskell . . . . . . . . . . . . . . . . . . . . . . . . Classes, Instncias e Polimorsmo Restrito . . . . . . . . . . . . . . . . Sistema de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Inferncia de Tipos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xix

3.5

3.4.1 Semntica . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Concluso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

39 41 43 43 45 47 50 54 59 61 62 63

4 Funes Polimrcas Restritas de Primeira Classe 4.1 Introduo . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Sintaxe . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Sistema de Tipos . . . . . . . . . . . . . . . . . . . . 4.4 Inferncia de Tipos . . . . . . . . . . . . . . . . . . . 4.5 Implementao . . . . . . . . . . . . . . . . . . . . . 4.6 Concluso . . . . . . . . . . . . . . . . . . . . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

. . . . . .

5 Concluso 5.1 Trabalhos Futuros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Referncias Bibliogrcas

xx

Captulo 1 Introduo
Tipos tm papel cada vez mais importante na construo de programas, na engenharia de software e no raciocnio sobre propriedades de programas. Eles servem como documentao e especicao parcial da funcionalidade de programas e possibilitam garantir que determinadas classes de erros nunca iro ocorrer quando o programa for executado, podendo tambm contribuir para gerao de cdigo mais eciente. Sistemas de tipos para linguagens de programao consistem em mtodos sintticos para provar a ausncia de determinados comportamentos indesejados de programas, por meio da classicao das frases do programa de acordo com os tipos de valores que elas computam. Esses comportamentos indesejados que podem ser eliminados por meio de sistemas de tipos so comumente denominados erros de tipo. Sistemas de tipos so necessariamente conservativos, ou seja, para garantir que programas bem tipados no esto sujeitos a erros de tipo, necessrio algumas vezes rejeitar programas cujo comportamento, em tempo de execuo, seria, de fato, correto. Por exemplo, um programa tal como if <teste complexo> then 5 else <erro de tipo> rejeitado como no corretamente tipado, mesmo no caso em que a avaliao de <teste complexo> sempre resulte True, j que, em geral, no possvel determinar que esse o caso por meio de anlise puramente sinttica. Pesquisas em sistemas de tipos para linguagens de programao buscam atribuir tipos cada vez mais informativos a expresses de programas, de maneira a eliminar o maior nmero possvel de comportamentos indesejados e ao mesmo tempo permitir que maior nmero de programas com comportamento desejado sejam considerados vlidos, ou bem tipados. 1

Captulo 1. Introduo

Um passo importante no sentido de obter uma disciplina de tipos que evite o uso de expresses em contextos inapropriados, levando em conta, ao mesmo tempo, o objetivo de possibilitar reuso de cdigo, foi a denio de sistemas de tipos polimrcos. Um tipo polimrco consiste em um esquema (conjunto, coleo) de tipos, envolvendo variveis de tipo universalmente quanticadas, e expressa que uma determinada funcionalidade oferecida para todas as instncias desse esquema de tipos. Por exemplo, o tipo da funo de aplicao que toma dois argumentos e aplica o primeiro argumento ao segundo pode ser escrito como a b. (a b) a b. Esse tipo expressa, de fato, toda uma coleo de tipos, obtidos pela instanciao de cada uma das variveis universalmente quanticadas para um tipo especco arbitrrio. A forma mais simples de polimorsmo paramtrico foi denida no sistema de tipos proposto independentemente por Hindley [16] e por Damas-Milner [10]. No sistema de Hindley-Milner (HM), quanticadores ocorrem apenas nas posies mais externas de esquemas de tipos: parmetros de funes no podem ter tipo polimrco. Toda expresso bem tipada no sistema HM pode ser caracterizada por um tipo principal um tipo cujo conjunto de instncias constitudo exatamente por todos os tipos que podem ser atribudos a essa expresso. Alm disso, o tipo principal de cada expresso pode ser inferido automaticamente, sem que seja requerida qualquer anotao de tipo em programas. O sistema HM tem sido usado como base para os sistemas de tipos de linguagens funcionais modernas, tais como ML [34] e Haskell [39], e as vantagens do uso de polimorsmo paramtrico tm sido cada vez mais reconhecidas, como mostra sua introduo tambm em linguagens como C# e Java verso 5. O sucesso do sistema HM devido sua expressividade e ao fato de possuir um algoritmo de inferncia de tipos relativamente simples. Outra forma importante de polimorsmo o chamado polimorsmo restrito, ou polimorsmo de sobrecarga [46], no qual uma determinada funcionalidade provida para diferentes tipos, com diferentes implementaes para cada tipo. Por exemplo, um teste de igualdade para uma lista de inteiros implementado de forma diferente do teste de igualdade para inteiros, ou para rvores, ou para valores booleanos. Em Haskell, o mecanismo de sobrecarga suportado por meio da denio de type classes, ou classes de tipos, originalmente proposto em [53]. Por exemplo, uma classe Eq, com operadores (==) e (/=) para igualdade e desigualdade, respectivamente, pode ser declarada do seguinte modo:

class Eq a where (==) :: a a Bool (/=) :: a a Bool Os operadores (==) e (/=) tm tipo polimrco restrito: a. Eq a a a Bool. A restrio de tipo (ou restrio de classe) Eq a indica que a varivel a pode ser instanciada apenas para tipos que sejam instncias da classe Eq. Uma denio de instncia de classe prov implementaes apropriadas para os smbolos declarados nessa classe. Por exemplo, tipos bsicos, como Int, podem ser denidos como instncias da classe Eq, sendo os testes de igualdade e desigualdade implementados por funes pr-denidas. Outros tipos tambm podem ser denidos como instncias da classe Eq, tal como no seguinte exemplo, que dene uma instncia para listas: instance Eq a [ ] == (x : xs) == xs /= Eq [a] where [ ] = True (y : ys) = (x == y) && (xs == ys) ys = not (xs == ys)

Nesse exemplo, o teste de igualdade para elementos de um tipo arbitrrio, mas xo, usado para denir a igualdade para listas de elementos desse tipo. Por meio dessa denio, o teste de igualdade pode agora ser usado para valores de tipo [Int], [[Int]], e assim por diante. E o mesmo vale para outras funes, denidas em termos do operador de igualdade, tais como: elem :: a. Eq a a a Bool elem y = foldr ( x r (x == y) || r) False A clara fundamentao matemtica de linguagens de programao funcional faz com que sejam particularmente apropriadas para a formalizao, anlise e experimentao de sistemas de tipos cada vez mais expressivos. Haskell, em particular, tem sido usada nas duas ltimas dcadas como um laboratrio para explorar, projetar e implementar idias novas e avanadas relacionadas a sistemas de tipos [17]. Um problema particularmente importante, que tem sido objeto de diversos trabalhos de pesquisa recentes, a extenso do sistema de tipos de Hindley-Milner de maneira a possibilitar a denio de funes com parmetros de tipos polimrcos. Por exemplo, considere a seguinte denio de funo:

Captulo 1. Introduo

Exemplo 1.1

foo g = (g [True,False], g [b,a,c])

Note que, no corpo da funo foo, o parmetro g aplicado a listas de dois diferentes tipos. Gostaramos que o tipo atribudo a foo fosse tal que possibilitasse, por exemplo, a aplicao de foo funo polimrca length, que computa o nmero de elementos de uma lista, dando como resultado, nesse caso, o valor (2,3). Mas tal aplicao no seria bem tipada no sistema de Hindley-Milner. Nesse sistema, poderamos atribuir a foo o tipo a.([a] Int) (Int, Int), que entretanto no seria satisfatrio. Esse tipo signica que foo uma funo polimrca que, para qualquer tipo especco, digamos, , toma como argumento uma funo de tipo [ ] Int e produz como resultado um valor de tipo (Int,Int). Mas, nesse caso, o tipo no poderia ser tanto [Bool] quanto [Char], como requerido pelos usos do parmetro (g) no corpo da funo foo (isto , nas aplicaes g [True,False] e g [b,a,c], respectivamente). A questo aqui que desejamos expressar que foo deve poder ser aplicada a um argumento de tipo polimrco, que possa ser instanciado para os tipos [Bool] Int e [Char] Int. Em um sistema mais expressivo, o tipo de foo poderia ser ( a.[a] Int) (Int, Int). Esse tipo no vlido no sistema HM, pois envolve quanticadores que aparecem internamente ao tipo, nesse caso do lado esquerdo do construtor de tipo funcional. De modo geral, podem ser necessrios tipos em que quanticadores possam ocorrer em qualquer posio. Essa possibilidade de tratar tipos polimrcos como qualquer outro tipo chamada de polimorsmo de primeira classe (ou polimorsmo de rank superior , ou de rank-n). Existem diversas aplicaes interessantes que requerem polimorsmo de rankn, apresentadas, por exemplo, em [45, 38, 50], incluindo abstraes sobre mnadas, denies de invariantes de tipos de dados e funes genricas (ou politpicas). Isso motivou a introduo de polimorsmo de rank-n em algumas implementaes correntes da linguagem Haskell [38]. O sistema F, de Girard-Reynolds [14, 42], tambm chamado lambda-calculus polimrco, ou lambda-caulculus de segunda ordem, constitui a referncia fundamental para polimorsmo de rank-n. Ao contrrio do que ocorre no sistema de Hindley-Milner, a inferncia de tipos no sistema F indecidvel [55]. Alm disso, no sistema F nem toda expresso possui tipo principal. Para contornar esses problemas, diversos trabalhos recentes buscam denir um sistema de tipos que suporte polimorsmo de rank-n, mas preserve a propriedade de tipo principal e a decidibilidade da inferncia de tipos, para isso requerendo anotaes explcitas de tipos em programas. Trabalhos relevantes nesse sentido so MLF [28, 29],

FPH [52] e Flexible Types [30, 31]. O uso de sistemas de tipos com suporte a polimorsmo de rank-n certamente introduz exibilidade e expressividade adicional na linguagem. Entretanto, em alguns casos tipos polimrcos no capturam de maneira adequada as restries que se deseja expressar em relao a parmetros de funes. Considere os seguintes usos da funo foo denida no exemplo 1.1 (foo id), (foo const), (foo reverse), (foo head), (foo sort), (foo allEqual), (foo fromEnum), (foo blah) onde id :: a. a a consti :: a. a Int reverse :: a. [a] [a] head :: a. [a] a sort :: a. (Ord a) [a] [a] allEqual :: a. (Eq a) [a] Bool fromEnum :: a. (Enum a) a Int blah :: a, b. (C a b) [a] [b] funo identidade funo constante inverso de lista primeiro elemento de lista ordenao todos os elementos iguais enumerao para inteiro

Os quatro primeiros argumentos so funes polimrcas paramtricas e os quatro ltimos funes com tipo polimrco restrito por predicados de classe, o que signica que tais funes so denidas por expresses que envolvem smbolos sobrecarregados. Uma possvel anotao de tipo para foo seria foo :: c d. (a b. a b) (c, d), mas esse tipo permitiria a aplicao de foo apenas funo undefined. Se a anotao de tipo para foo :: b. (a. a b) (b, b), a nica dentre as aplicaes acima que seria bem tipada seria (foo const) (com tipo (Int,Int)). Para que a aplicao (foo id) seja bem tipada, a anotao de tipo deve ser foo :: (a. a a) ([Bool], [Char]) e, nesse caso, os demais usos de foo relacionados acima no seriam vlidos. A aplicao (foo sort) pode ser permitida em um sistema de tipos tal como QMLF [33]. Esse sistema de tipos estende o sistema MLF de maneira a permitir tipos polimrcos de rank-n com restries. Como observa o prprio autor, a maior diculdade para prover essa extenso no reside propriamente nas modicaes requeridas nas regras do sistema de tipos MLF ou no seu mecanismo de inferncia de tipos, mas sim na implementao do sistema resultante, que deve lidar corretamente com o mecanismo usual de implementao de funes sobrecarregadas, baseado no uso de dicionrios [53]. Em implementaes de Haskell com tal extenso, a aplicao (foo sort) bem

Captulo 1. Introduo

tipada se a anotao de tipo provida para foo for, por exemplo foo :: (a. (Ord a) [a] [a]) ([Bool], [Char]) sendo nesse caso tambm bem tipada a aplicao (foo id), j que o tipo de id pode ser instanciado para o tipo do parmentro de foo, no sistema QMLF. Entretanto, essa anotao de tipo no possibilitaria a aplicao (foo buzz), onde buzz::(a. (C a) [a] [a]) ([Bool], [Char]) uma funo com tipo polimrco quase idntico ao de sort, mas porm com uma restrio de classe (C a), em que C uma classe distinta de Ord. Neste trabalho, buscamos denir um sistema de tipos no qual seja possvel expressar de maneira mais adequada e precisa o tipo de uma funo com parmetro polimrco, tal como a funo foo do exemplo acima, possibilitando o uso dessa funo, por exemplo, em qualquer das expresses consideradas anteriormente. Ou seja, o tipo de foo deve expressar adequadamente que o seu parmetro uma funo que pode ser aplicada tanto a um argumento de tipo [Bool] como a um argumento de tipo [Char] e, alm disso, que o primeiro e o segundo componentes do par resultante devem ter tipo, respectivamente, igual ao do valor resultante da aplicao do argumento de foo a uma expresso de tipo [Bool] e a uma expresso de tipo [Char]. Para expressar esses requerimentos de maneira adequada, o sistema de tipos proposto utiliza uma forma restrita de tipos interseo [8]. Nesse sistema, o tipo da funo foo do exemplo 1.1 poderia ser anotado como foo :: a b. ([Bool] a [Char] b) (a, b) Mediante essa anotao de tipo na denio de foo, qualquer das aplicaes anteriormente seria vlida. Por exemplo, (foo id) :: ([Bool], [Char]), (foo consti) :: (Int, Int) e (foo blah) :: a b. (C Int a, C Bool b) (a, b). Nesse ltimo caso, a sobrecarga pode ainda ser resolvida, de acordo com o contexto em que essa expresso for utilizada. As contribuies dessa dissertao so: 1. A denio de um sistema de tipos original, que denominamos CTi, que prov suporte a passagem de funes sobrecarregadas para funes de rank superior, isto , funes usadas polimorcamente na sua prpria denio. 2. Uma descrio (informal) da semntica para termos da linguagem do sistema CTi.

1.1. Organizao

3. A denio de um algoritmo para inferncia de tipos para o sistema CTi. 4. Uma implementao desse algoritmo de inferncia de tipos, em Haskell, para inferncia de tipos para expresses de uma linguagem de programao que consiste em uma extenso de Haskell para suporte ao sistema de tipos proposto. 5. A elaborao de uma reviso sobre sistemas de tipos para liguagens de programao, que aborda o sistema de tipos polimrcos de let-bound de Hindley-Milner, a extenso desse sistema para suporte a sobrecarga e sistemas com suporte para funes de rank superior. Essa reviso, embora no seja original, contribui para difundir e disseminar o assunto, particularmente para leitores ainda no muito experientes. Um dos objetivos do sistema de tipos aqui proposto, servir como base para a denio de um sistema ainda mais exvel, que possibilite a passagem de funes sobrecarregadas g como argumento para uma funo f , de maneira que, no corpo de f , g possa ser aplicada a estruturas de dados com elementos de tipos heterogneos, tais como uma lista heterognea. A idia denir o tipo dessa lista heterognea como um tipo [T ], em que T representa todos os possveis tipos de elementos dessa lista; uma lista com tal tipo poderia ser usada seguramente (sem possibilidade de erros de tipo) como argumento de uma funo sobrecarregada g, se, para cada um dos tipos representados por T , existe uma denio de uma instncia em que o parmetro de g tem esse tipo.

1.1

Organizao

O restante do texto est organizado da seguinte forma. O Captulo 2 apresenta uma reviso do sistema de tipos polimrcos de rank-1 proposto por Hindley e Milner (HM) e uma reviso sucinta sobre sistemas de tipos polimrcos de rank superior, incluindo o sistema F, proposto por Girard e Reynolds. Este Captulo tambm discute brevemente alguns trabalhos que propem extenses de HM para suporte a polimorsmo de rank superior. O Captulo 3 apresenta uma extenso do sistema HM para suporte a sobrecarga, baseada no sistema de classes de tipos de Haskell, a qual constitui a base para o sistema proposto nesse trabalho. Os dois Captulos tambm introduzem tambm os conceitos e notao relativas a sistemas de tipos usados na paresentao do sistema de tipos proposto.

Captulo 1. Introduo

O Captulo 4 apresenta as regras do sistema de tipos CTi, proposto neste trabalho, assim como uma semntica para expresses desse sistema e uma denio do algoritmo de inferncia de tipos correspondente. Finalmente, no Captulo 5 so apresentadas as concluses do trabalho.

Captulo 2 Polimorsmo Paramtrico


Este captulo prov uma reviso sobre sistemas de tipos com suporte a polimorsmo paramtrico. A Seo 2.1 introduz a linguagem de tipos e expresses usada como base para a denio desses sistemas de tipos e dene formalmente a noo de rank de tipos polimrcos. A Seo 2.2 aborda polimorsmo de rank -1, apresentando o sistema de tipos de Hindley-Milner[16, 10], assim como a inferncia de tipos para esse sistema e a semntica de termos da sua linguagem. O sistema HM, usado como base para linguagens funcionais modernas, tem a importante propriedade de que o tipo de qualquer expresso da linguagem pode ser inferido automaticamente, sem que qualquer anotao explcita de tipo seja requerida em programas. Entretanto, quase toda extenso desse sistema, como por exemplo a introduo de polimorsmo de rank superior, destri essa propriedade, requerendo a introduo de anotaes de tipo em determinados pontos do programa, de modo a garantir decidibilidade da inferncia de tipos. A Seo 2.3 discute polimorsmo de rank superior, apresentando o sistema F [18], que constitui a referncia bsica para sistemas de polimorsmo de rank arbitrrio. Na Seo 2.3.2 discutimos sucintamente alguns trabalhos recentes que buscam denir sistemas de tipo de ordem superior preservando a decidibiliade da inferncia de tipos, por meio do requerimento de anotaes de tipo em determinados pontos do programa, e mantendo compatibilidade com o sistema HM, na ausncia de anotaes de tipo.

2.1

Conceitos Bsicos

A linguagem bsica de tipos a ser utilizada nos sistemas de tipos discutidos neste captulo apresentada na Figura 2.1; Extenses dessa linguagem de tipos introduzidas oportunamente. 9

10

Captulo 2. Polimorfismo Paramtrico

Hyndley-Milner rank 1 ::= Variveis de tipo Tipos monomrcos Tipos polimrcos Contexto de tipos

sistema F rank arbitrrio ::= | a, b, c ::= ::= ::=

a | 1 2 a. | , x :

Figura 2.1. Sintaxe de tipos

Tipos monomrcos ( ) consistem de tipos simples, representados por variveis de tipo (a, b), e tipos funcionais (o construtor de tipos funcionais () escrito de forma inxada, como usual). Outros construtores de tipo comumente usados em linguagens de programao podem tambm ser includos, se desejado. Tipos polimrcos () incluem quanticao universal sobre variveis de tipo. A notao a usada nessa Figura, assim como no restante do texto, para representar uma seqncia de zero ou mais variveis de tipo a1 , . . . , an . A notao a. no necessariamente representa quanticao sobre todas as variveis de tipo livres de , ou seja, um tipo polimrco pode ter variveis de tipo livres. Dizemos que um tipo fechado se ele no possui variveis livres. A Figura 2.1 introduz tambm a denio de um contexto de tipos (), que prov informao sobre os tipos de variveis visveis em um dado escopo. A associao de um tipo a uma varivel x no contexto de tipos denotada por x : . A notao (x) denota o tipo associado varivel x no contexto e x denota o contexto obtido removendo-se de a atribuio de tipo a x que eventualmente ocorra nesse contexto. Denimos , (x : ) = x {(x : )} e [x,] = x , (x : ) se (x : ) x caso contrrio

O conjunto de variveis livres de um tipo , f tv(), denido da maneira usual, sendo essa denio tambm estendida para contextos de tipos da maneira usual, ou seja, f tv() = {f tv() | (x : ) }. Escrevemos abreviadamente f tv(o, o ) para denotar o conjunto de variveis f tv(o) f tv(o ), para objetos o e o . A notao [a ] denota o tipo obtido pela substituio simultnea, em , de

2.1. Conceitos Bsicos

11

Termos

t, u ::= | | | |

x Varivel x. t Abstrao funcional tu Aplicao let x = u in t Denio local t :: Anotao de tipo ( fechado)

Figura 2.2. Sintaxe do lambda-calculus

todas as ocorrncias livres de cada uma das variveis a1 , . . . , an a, n 0, pelo tipo correspondente 1 , . . . , n , sendo essa substituio vlida apenas se no resulta em captura de variveis livres em . 1 Essa substituio tambm escrita na forma S, onde S uma funo de variveis de tipo em tipos e S(ai ) = i , para i 0 e S(b) = b, se b a. A composio de duas substituies R e S denida da maneira usual e escrita como R S. Os sistemas de tipos a serem considerados neste trabalho diferem na sua denio dos tipos intermedirios , cuja caracterstica no apresentar quanticadores no nvel mais externo. No sistema de tipos de Hyndley-Milner, quanticadores ocorrem apenas no nvel mais externo, restringindo o sistema a polimorsmo de rank-1. O sistema F inclui tipos polimrcos de rank arbitrrio. O rank de um tipo descreve a profundidade na qual quanticadores universais ocorrem em posio contravariante no tipo [26]: Tipos monomrcos Tipos polimrcos Por exemplo: Int Int a.a a Int (a.a a) (a.a a) Int Rank Rank Rank Rank 0 1 1 2 , 0 n+1 ::= ::= a | 1 2 n | n n+1 | a. n+1

A sintaxe da linguagem de termos (ou expresses) dos sistemas de tipos discutidos nesse trabalho apresentada na Figura 2.2. A linguagem consiste do lambda-calculus [2] estendido com denies locais no recursivas (let-bindings) e com a possibilidade de incluir anotaes de tipos explcitas. Denies locais recursivas so omitidas uma vez que no introduzem diculdade adicional do ponto de vista da inferncia de tipos.
Veja [40] para uma denio precisa das noes de variveis livres e de substituio sem captura de variveis.
1

12

Captulo 2. Polimorfismo Paramtrico

2.2

Polimorsmo de Rank-1

A possibilidade de incluso de anotaes de tipo explcitas, escritas usando ::, considerada pelas seguintes razes: 1) para mostrar como anotaes de tipo podem ser usadas para dirigir a inferncia de tipos, de uma maneira simples e previsvel; 2) no sistema de tipos proposto nesse trabalho, anotaes de tipo sero usadas para possibilitar inferir tipos que no seriam inferidos no sistema HM, sendo mantida total compatibilidade com esse sistema na ausncia de anotaes de tipo. Supomos, por simplicidade, que os tipos especicados em anotaes de tipo so fechados, isto , no incluem variveis de tipo livres. O sistema de tipos de Hindley-Milner[16] (tambm chamado de DamasMilner[10]) foi um dos primeiros sistemas de tipos a incorporar uma forma simples de polimorsmo (let-bound ) que possibilita a denio de funes polimrcas de rank1. Sistemas de tipos de linguagens de programao funcionais modernas, tais como Haskell[39] e ML[34], e at mesmo linguagens imperativas, como Java (a partir de sua verso 1.5, com a introduo de classes genricas), baseiam-se na idia de polimorsmo introduzida por este sistema de tipos. A utilidade de polimorsmo paramtrico em linguagens de progtramao largamente reconhecida, e pode ser ilustrada por meio dos exemplos a seguir, escritos na linguagem Haskell. O primeiro exemplo apresenta a denio de uma funo length, que retorna o comprimento de uma lista. Note que o tipo da funo polimrco, o que possibilita que essa funo possa ser aplicada a listas de elementos de qualquer tipo, evitando que se tenha que prover uma nova denio para essa funo para listas de cada tipo sobre a qual se deseja aplicar essa operao, como seria o caso em um sistema de tipos monomrco. length :: [a] -> Int length [] = [] length (x:xs) = 1 + length xs Outro exemplo o da funo map, que captura o padro de computao da operao de aplicar uma determinada operao a todos os elementos de uma lista. Essa funo pode ser denida (recursivamente) do seguinte modo: map :: (a -> b) -> [a] -> [b] map f [] = [] map f (x:xs) = f x : map f xs Note que, como map tem tipo polimrco, pode ser aplicada a listas de elementos

2.2. Polimorfismo de Rank -1

13

de diferentes tipos, tal como, por exemplo, nas expresses: map (+1) [1, 2, 3] = [2, 3, 4] map not [True, False] = [False, True] map even [1, 2, 3] = [False, True, False] Polimorsmo paramtrico pode tambm ser usado na denio de tipos algbricos, tal como no exemplo a seguir, em que denido o tipo polimrco Tree a, que representa rvores binrias que armazenam nas folhas valores de um tipo a arbitrrio. data Tree a = Node (Tree a) (Tree a) | Leaf a

2.2.1

Sistema de Tipos

O sistema de tipos HM apresentado na Figura 2.3, na forma de um conjunto de regras para a derivao de um julgamento da forma t:

que especica que o termo t tem tipo no contexto de tipos . Note entretanto que vrias regras incluem julgamentos da forma t : , como, por exemplo, a regra (APP), signicando, nesse caso, que o tipo no possui quanticadores. A regra (VAR) especica que o tipo de uma varivel determinado pela informao ::= , (x : ) , (x : ) t : x. t :
(ABS)

t:
(VAR)

x: t: tu: t: (t :: ) : u:
(APP)

u : , (x : ) t : let x = u in t : t : a f tv() t : a.

(LET)

(ANNOT)

(GEN)

e : a. t : [a ]

(INST)

Figura 2.3. Sistema de Tipos HM

14

Captulo 2. Polimorfismo Paramtrico

de tipo correspondente disponvel no contexto . A regra (APP) determina que uma aplicao bem tipada apenas se o tipo do argumento igual ao do parmetro da funo. A regra (ABS) estabelece que uma abstrao funcional x. t tem tipo , em um dado contexto , se possvel deduzir que t tem tipo , em um contexto anlogo a , mas estendido de modo a associar a x o tipo . A regra (LET) determina que uma expresso let x = u in t tem tipo , em um contexto , se podemos deduzir que u tem tipo nesse contexto, e que t tem tipo em um contexto que consiste em estendido com a atribuio de tipo para a varivel x. A regra (INST) especica que o sistema predicativo, isto , variveis de tipo apenas podem ser instanciadas para tipos monomrcos. Em um sistema impredicativo, tal como o sistema F por exemplo, variveis de tipos podem ser instanciadas para tipos polimrcos. A regra (GEN) possibilita a generalizao do tipo de uma expresso por meio de quanticao sobre variveis de tipo que no ocorram livres no contexto. A Figura 2.4 ilustra uma derivao de tipo no sistema HM (nesta derivao, usamos y = {y : b. b b}).

(VAR) y y : b. b b y y : b. b b x : x : b (ABS) (INST) y y : [b := a](b b) x.x : b b (GEN) y y : [b a a](b b) x. x : b. b b y y y : a a (LET) let y = x. x in y y : a a

(VAR)

(VAR) (INST) (APP)

Figura 2.4. rvore de derivao de tipo

A regra (ANNOT) no includa na maioria das apresentaes do sistema HM, uma vez que anotaes de tipo no so requeridas nesse sistema. Optamos entretanto por incluir anotaes de tipo, com o objetivo de facilitar o entendimento do sistema de tipos proposto no captulo 4, no qual anotaes de tipo possuem papel fundamental. Um termo (t :: ) um termo cujo tipo explicitamente anotado pelo programador. Por exemplo, considere o termo: (x. x) :: a. [a] [a] Esse termo bem tipado, uma vez que o tipo mais geral de (x. x) a. a a, o qual mais geral do que o tipo anotado a. [a] [a]. A anotao uma restrio de tipo, porque o termo cujo tipo anotado apenas pode ser usado com o tipo especicado (ou com tipos que so instncias deste). Por exemplo, a anotao invalida a aplicao ((x. x) :: a. [a] [a]) True, embora (x. x) possa ser aplicado a True.

2.2. Polimorfismo de Rank -1

15

No sistema HM, a regra (ANNOT) bastante simples: ela apenas requer que o tipo anotado para um termo (t :: ) de fato possa ser derivado para esse termo.

2.2.2

Sistema de Tipos Dirigido por Sintaxe

Inferncia de tipos pode ser denida como o problema de reconstruir anotaes de tipo para um termo no explicitamente tipado, ou que inclui apenas anotaes parciais de tipo. Em outras palavras, consiste no problema de determinar, dado um termo t e um contexto de tipos inicial 0 (possivelmente vazio) se existe uma tipagem (, ) tal que e : e 0 . Esse problema importante tanto do ponto de vista terico como pragmtico, j que desejamos programar em linguagens estaticamente tipadas, em que erros de tipo so detectados em tempo de compilao, mas desejamos incluir o mnimo de anotaes de tipo em programas, j que isso em geral tedioso e anotaes de tipo excessivas podem prejudicar a clareza de programas. No sistema apresentado na Figura 2.3, cada regra tem na concluso uma forma sinttica distinta, exceto as regras de generalizao (GEN) e de instanciao (INST). Como essas regras tm a mesma forma sinttica como premissa e como concluso, elas podem ser aplicadas em qualquer instante da derivao; por exemplo, poderamos alternar (GEN) e (INST) indenidamente. Portanto difcil obter um algoritmo de inferncia de tipos a partir dessas regras, no sendo claro que regras usar, e em que ordem, para derivar um julgamento de tipo para um dado termo t em um contexto . Se todas as regras tm uma forma sinttica distinta em sua concluso, dizemos que o sistema est na forma dirigida por sintaxe, o que determina completamente a forma da rvore de derivao de tipo para um termo particular t. Isso desejvel, pois signica que o algoritmo de inferncia de tipos pode ser dirigido pela sintaxe de termos, no sendo necessria uma busca exaustiva por uma derivao de tipo vlida. A Figura 2.5 apresenta uma forma alternativa de regras de derivao de tipos dirigida por sintaxe para o sistema HM. 2 Nessa formulao, tipos polimrcos ocorrem apenas no contexto de tipos. Os locais em que generalizaes e instanciaes so requeridas so agora determinados pela sintaxe de termos: a instanciao de tipos ocorre apenas na regra (VAR)e a generalizao ocorre apenas na (LET). Portanto, as regras derivam julgamentos da forma t : , onde um tipo monomrco.
Uma prova da equivalncia entre esse sistema e o sistema no dirigido por sintaxe apresentado anteriormente pode ser encontrada em [7].
2

16

Captulo 2. Polimorfismo Paramtrico

::=
inst

t:
(VAR)

, (x : ) x :

, (x : ) t : x. t :


(ABS)

t: u: tu: t: (t :: ) :
gen

(APP)

gen u : , (x : ) t : let x = u in t :

(LET)

inst

(ANNOT)

gen

t:

inst

a = f tv() f tv() t: gen t : a.

(GEN)

inst

(INST)

a. [a ]

Figura 2.5. Sistema de tipos HM dirigido por sintaxe

A instanciao tratada por meio do julgamento auxiliar


inst

que signica que os quanticadores de podem ser instanciados de modo a obter . Se inst dizemos que uma instncia de (e que pode ser instanciado para o tipo ). De forma dual, a generalizao tratada por meio do julgamento auxiliar
gen

t:

que infere um tipo polimrco para um termo, sendo este julgamento usado na regra (LET) para atribuir tipo varivel denida nessa construo. A regra (GEN) especica que as variveis de tipo quanticadas a devem ser exatamente as variveis que ocorrem livres em e no ocorrem livres em : no h necessidade de generalizar sobre variveis que no ocorram livres em e, por outro lado, necessrio generalizar o mximo

2.2. Polimorfismo de Rank -1

17

possvel.

2.2.3

Inferncia de Tipos

As regras do sistema apresentado na Figura 2.5 no denem um algoritmo, j que em vrias delas ocorre um tipo no especicado: por exemplo, o tipo que ocorre como tipo do parmentro da lambda abstrao, na regra (ABS). Dado um contexto de tipos vazio, e o termo x. x, os seguintes julgamentos de tipo seriam vlidos, escolhendo o tipo como sendo Int, [a] ou a, respectivamente: (x. x) : Int Int (x. x) : [a] [a] (x. x) : a a claro que o algoritmo de inferncia de tipos deve inferir o ltimo desses tipos, pois o tipo mais geral para (x. x) (a menos de quanticao sobre a varivel a). Do mesmo modo, na regra (INST) precisamos adivinhar os tipos para os quais as variveis quanticadas a devem ser instanciadas. A idia para obter o algoritmo de inferncia de tipos utilizar novas variveis de tipo (fresh) em lugar de tipos no especicados, determinando o tipo requerido posteriormente, por meio de unicao [44]. A unicao de dois tipos (monomrcos) 1 e 2 , escrita como unify(1 = 2 ), determina a substituio mais geral S que unica esses dois tipos, caso tal substituio exista Mais formalmente, se S = unify(1 = 2 ), ento S satisfaz as seguintes propriedades: i) S1 = S2 ; ii) para toda substituio S tal que S 1 = S 2 , existe uma substituio R tal que S = R S (onde denota composio funcional). O algoritmo de inferncia de tipos para HM foi proposto originalmente por Damas e Milner [10]. Esse algoritmo apresentado na Figura 2.6, como um conjunto de regras de inferncia para julgamentos da forma t : (, )

signicando que a tipagem ( , ) inferida para o termo t, dado um contexto de tipos inicial . Note que variveis fresh so utilizadas nas regras (ABS) e (VAR), em lugar dos tipos indeterminados Nesta ltima regra por meio da redenio da relao de ins-

18

Captulo 2. Polimorfismo Paramtrico

::=
inst

t : (, )
(VAR)

, (x : ) x : (, )

a fresh x , (x : a) t : (, ) x. t : ( (x) , [x,] )


gen

(ABS)

t : (, 1 ) 1 u : (, 2 ) a fresh S = unify( = a) t u : (Sa, S2 ) t : ( , ) inst (t :: ) : (, )


sh

(APP)

gen

u : (, 1 ) 1 t : (, ) let x = u in t : (, [x,] )

(LET)

(ANNOT)

gen

t : (, )

inst

a = f tv() f tv( ) t : (, ) gen t : (a. , )

(GEN)

inst

b fresh a. [a b]

(INST)

sh

a f tv() sh
sh (SKOL)

sh

a.

sh

[a ]1 2 a. 1 2

(SPEC)

sh

(MONO)

Figura 2.6. Inferncia de tipos para HM

tanciao ( inst ), na qual as variveis quanticadas do tipo a ser instanciado so substitudas por variveis fresh. A determinao do tipo requerido feita por meio do processo de unicao, na regra (APP). Na regra (ABS), o tipo da expresso que dene o corpo da funo inferido no contexto de tipos x , (x : a), signicando que qualquer atribuio de tipo para uma varivel de nome igual ao do parmetro da funo (x) retirada do contexto, sendo

2.2. Polimorfismo de Rank -1

19

introduzido nesse contexto o tipo (x : a), onde a uma varivel fresh. O tipo da varivel x que eventualmente ocorra no escopo externo lambda-abstrao recuperado no contexto resultante ([x,] ), na concluso dessa regra. O mesmo processo usado na regra (LET), para restringir o escopo da varivel denida nessa construo. No sistema de tipos apresentado na Figura 2.3, a regra para anotao de tipo bastante simples: ela apenas requer que um termo (t :: ) de fato tenha tipo . Na inferncia de tipos, a regra (ANNOT) verica o tipo anotado em trs passos: Obter o tipo mais geral para t, ou seja , usando
gen

Esse tipo pode ser diferente do tipo anotado , pois esse ltimo no necessariamente o tipo mais geral de T . Portanto, o prximo passo vericar se o tipo mais geral (ou mais polimrco) do que , o que feito por meio do julgamento sh (o superescrito sh indica subsuno); Finalmente, instanciar , usando Diferentemente de Por exemplo:
inst inst

.
sh

, o julgamento

compara tipos polimrcos.

Int Bool a. a a a. a a ab. (a, b) (b, a)

Int Bool Int Int b. [b] [b] c. (c, c) (c, c)

Na denio do julgamento sh , a regra (MONO) lida com o caso trivial de dois tipos monomrcos. No caso mais geral, provar sh , implica mostrar que toda instncia de tambm uma instncia de . Formalmente, para provar sh a. b. devemos provar que: b . a . [a a ] [b b ] Para isso, a regra (SPEC) nos permite instanciar as variveis de tipo quanticadas de , de maneira a obter . Mas como podemos vericar que pode ser instanciado, por meio de (SPEC), para qualquer instncia de ? A idia instanciar as variveis quanticadas de para novas constantes de tipo arbitrrias (fresh), denominadas constantes de Skolem, e ento vericar se pode ser instanciado para o tipo obtido por esse processo de skolemizao. De fato, a regra (SKOL) no instancia as variveis de para novas constantes de tipo arbitrrias, mas, equivalentemente, apenas verica que essas variveis so novas em relao a (isto , que no ocorrem no conjunto de variveis livres de , considerando-se possvel renomeao de variveis ligadas em ).

20

Captulo 2. Polimorfismo Paramtrico

Note que a regra (SKOL) deve ser aplicada antes da regra (SPEC), uma vez que esta ltima pressupe um tipo do lado direito de . Ou seja, primeiro instanciamos para constantes de Skolem, e ento escolhemos como instanciar de modo a casar com o tipo obtido por skolemizao de . Por exemplo, para provar que a. a a b c. (b, c) (b, c) primeiro usamos a regra (SKOL) para skolemizar b e c, vericando que b e c no ocorrem livres em a. a a, e ento usamos a regra (SPEC) para instanciar a para (b, c). A derivao tem a seguinte forma: [a (b, c)]a a (b, c) (b, c) (INST) a. a a (b, c) (b, c) (SKOL) a. a a b c. (b, c) (b, c) A relao sh pode ser implementada usando skolemizao e unicao, como se mostra a seguir, onde as variveis cK representam novas constantes de tipo, que portanto no podem ocorrer no domnio da substituio retornada pela unicao. cK fresh S = unify( = [a cK ])
sh (SKOL) inst (MONO)

a.

Sistemas de tipos polimrcos possibilitam, em geral, obter diferentes derivaes de tipo para uma dada expresso em um determinado contexto. importante portanto que o tipo inferido para uma expresso, em um dado contexto, seja o tipo mais geral que pode ser derivado para a expresso nesse contexto, j que a semntica de expresses deve poder ser dada em termos da derivao do tipo inferido. Para formalizar o enunciado dessa propriedade de tipo para o algoritmo acima, necessrio introduzir uma denio de ordem entre contextos de tipo, a qual denida em termos da relao de ordem entre tipos sh : dom() = dom( ) e para todo (x : ) e (x : ) , sh
sh

A inferncia de tipos no sistema HM satisfaz as seguintes propriedades importantes, que garantem a sua coerncia em relao ao sistema de tipos (para uma prova dessas

2.2. Polimorfismo de Rank -1

21

propriedades veja, por exemplo [40, 35]): Teorema 2.2.1 (Correo) Para todo termo t, se t : (, ) ento t: t :

Teorema 2.2.2 (Tipo Principal) Para todo termos t, se (, ), onde sh e gen t : ( , ) sh .

t : , ento

2.2.4

Semntica

De maneira geral, existem dois estilos de atribuir signicado a termos de uma linguagem tipada, usualmente denomidados intrnseco ou extrnseco ou, alternativamente, estilo Church e estilo Curry[2], respectivamente. No estilo Church, a semntica denida sobre derivaes no sistema, sendo portanto atribudo signicado apenas a termos bem tipados. Nessa viso, a noo de tipo anterior noo de signicado e, portanto, no faz sentido a questo qual o comportamento de um termo no tipado?. Uma semntica em estilo Curry, por outro lado, atribui signicado aos termos independentemente de seu tipo (portanto, termos no envolvem anotaes de tipo), sendo esse signicado o mesmo que na verso no tipada da linguagem. Em outras palavras, nessa viso primeiro so denidos os termos (no tipados) e sua semntica (por meio de regras de reduo), sendo posteriormente denido um sistema de tipos, que rejeita termos cujo comportamento indesejado. A semntica de expresses do sistema HM denida na Figura 2.7, em estilo Church, sobre derivaes do sistema de tipo dirigido por sintaxe: t: t

onde o termo t tem tipo no contexto , tendo signicado t . Nessa Figura, omitimos as denies das relaes inst e gen , uma vez que no so relevantes para a semntica de termos. O mecanismo fundamental para a denio de semntica dos termos de HM a reduo[1], que prov uma noo de um passo de avaliao (ou computao) dos termos da linguagem. Uma aplicao da forma (x.t) u reduz para a expresso [x u]t, isto , para o termo obtido pela substituio no termo t de todas as ocorrncias livres da varivel x pelo termo u, sendo essa substituio vlida apenas se no resulta em captura de variveis livres em u. Por Exemplo a substituio [x y](y.xy) no seria vlida, j que resultaria no termo (y.yy), em que a varivel livre x capturada nesse processo de substituio.3
Veja, por Exemplo [1, 2, 40] para uma denio precisa das noes de variveis livres e substituio sem captura de variveis.
3

22

Captulo 2. Polimorfismo Paramtrico

::=
inst

t:

t
(VAR)

, (x : ) x :

x t: (x. t ) u: u tu: [x u ]t

, (x : ) t : t x. t : x. t gen u : u , (x : ) t : let x = u in t :

(ABS)

(APP)

t [x u ]t

(LET)

gen t : t sh inst gen (t :: ) : t

(ANNOT)

Figura 2.7. Semntica do sistema HM

A propriedade mais fundamental de um sistema de tipos correo (em ingls, safety ou soundness), que garante que a avaliao de um termo bem tipado no resulta em erro de tipo: sua execuo no falha inesperadamente. Isso determinado estaticamente, isto , sem que o programa seja executado, o que prov ao programador uma garantia parcial de robustez ou segurana do programa. A prova de que o sistema HM correto em relao semntica denida na Figura 2.7 deriva diretamente das duas seguintes propriedades mais fundamentais (para uma prova dessas propriedades, veja, por Exemplo, [35, 40]). Teorema 2.2.3 (Progress) : Seja t um termo fechado da linguagem tal que Ento t : t , para algum termo t . t : .

Intuitivamente, essa propriedade garante que todo termo bem tipado t pode ser avaliado segundo as regras de avaliao de expresses da linguagem, ou seja, t um valor ou pode ser reduzido para algum termo t . Teorema 2.2.4 (Preservation) : Se t: t ento t :.

Intuitivamente, o esse teorema garante que o termo resultante da aplicao de um passo de avaliao sobre um termo bem tipado tambm um termo bem tipado, e tem o mesmo tipo principal que o tipo original.

2.3. Polimorfismo de Rank Superior

23

2.3

Polimorsmo de Rank Superior

Sistemas com suporte para polimorsmo de rank arbitrrio (ou rank-n) so mais expressivos que o sistema HM, possibilitando denir funes com parmetros de tipo polimrco, tais como no Exemplo 1.1 (3), apresentado anteriormente. Nesse Exemplo, o parmetro g usado polimorcamente no corpo da funo foo, sendo aplicado a listas de booleanos e listas de caracteres, o que reetido na anotao de tipo provida para a funo foo. A aplicao foo reverse, por Exemplo, seria vlida, produzindo como resultado ([False, True], [c,a,b]). A denio da funo foo, entretanto, no seria bem tipada no sistema HM, pois esse sistema requer que parmetros de funes tenham tipo monomrco o sistema de tipos pode atribuir a g o tipo [Int] [Int] ou [Bool] [Bool], mas no o tipo polimrco a. [a] [a], o que apenas seria permitido em um sistema com suporte para polimorsmo de rank superior. Aplicaes mais interessantes de tipos polimrcos de rank superior so descritas em [45, 38, 50]. Coloca-se portanto a questo: possvel estender o sistema HM de modo a considerar tipos polimrcos de rank superior, mas sem que o sistema resultante, ou o mecanismo de inferncia de tipos, seja demasiadamente complicado? Alguns trabalhos que buscam dar resposta a essa questo so discutidos na Seo 2.3.2. A referncia fundamental para sistemas de polimorsmo de rank arbitrrio (ou rank-n) o sistema F proposto simultaneamente por Girard[14, 18] e Reynolds[43], tambm chamado de lambda calculus de segunda ordem, devido a sua correspondncia com a Lgica Intuicionista de Segunda Ordem (veja [14, 18]). O sistema F no entretanto adequado como base para a implementao de suporte a polimorsmo de rank superior em linguagens de programao, porque no possui a propriedade de tipo principal e a inferncia de tipos nesse sistema indecidvel [55]. O sistema F comumente usado como linguagem objeto para a denio de semntica de extenses do sistema HM, tanto para suporte a polimorsmo de rank superior como para polimorsmo de sobrecarga, e tem sido usado como linguagem objeto em compiladores de linguagens funcionais modernas.

2.3.1

Sistema F

A linguagem de tipos () do sistema F como denida anteriormente (na Seo 2.1): note que = | . A linguagem de termos e expresses do sistema F (explicitamente tipado) apresentada na Figura 2.8. Nessa linguagem, cada ocorrncia ligada de varivel anotada com seu respectivo tipo. Uma aplicao de tipo explcita (e ) especica os tipos que instanciam uma funo polimrca f e uma abstrao de tipo

24

Captulo 2. Polimorfismo Paramtrico

Expresses

e,f

::= | | | | |

x a. e (x : ).e (e ) (f e) let (x : ) = e1 in e2

Variveis Abstrao de tipo Abstrao funcional Aplicao de tipo Aplicao de valor Denio local

Figura 2.8. Sintaxe da linguagem do sistema F

= | , (x : ) , (x : ) e : (x :: ). e : e: a. e : a.
(ABS)

e:
(VAR)

x: f : e: (f e) : a. e : a. (e ) : [a ]
(LET) (APP)

(TABS)

(APP2)

e1 : , (x : ) e : let (x :: ) = e1 in e2 :
Figura 2.9. Sistema F

explcita (a. e) especica como e onde feita generalizao sobre variveis de tipo. Denies locais so includas na linguagem apenas por convenincia, embora no sejam necessrias, j que uma denio local let (x :: ) = e1 in e2 equivalente aplicao (((x :: ). e2 ) e1 ). As regras de derivao de tipo para expresses do sistema F so apresentadas na Figura 2.9. No sistema F possvel atribuir tipo, por Exemplo, expresso x.x x (de fato, uma quantidade innitamente enumervel de tipos), tal como, por Exemplo, os tipos (a. a) (a. a) ou (a. a a) (a. a a). Note que nenhum desses dois tipos instncia um do outro; e possvel mostrar que nenhum outro tipo derivvel para essa expresso mais geral do que ambos (isto , pode ser instanciado para cada um deles), o que signica que o sistema F no possui a propriedade de tipo principal.

2.3. Polimorfismo de Rank Superior

25

2.3.2

Estendendo HM com polimorsmo de rank-n

Alguns trabalhos recentes propem extenses ao sistema HM no sentido de prover polimorsmo de rank superior, buscando manter compatibilidade com HM na ausncia de anotaes de tipo (isto , nesse caso, o tipo inferido deve ser o mesmo que o obtido em HM), mas usar anotaes de tipo explcitas para possibilitar a denio de funes de ordem superior, buscando prover a mesma expressividade do sistema F. claro que tambm desejvel que os requerimentos de anotaes de tipo em programas sejam mnimos. Para isso, a idia propagar a informao provida pelas anotaes de tipo ao longo do programa (durante a inferncia de tipos), evitando assim o requerimento de anotaes de tipo redundantes. A idia de propagar anotaes de tipo em programas, usando essa informao para guiar a inferncia de tipos foi primeiramente proposta por Pierce and Turner [41], sendo chamada de inferncia de tipos local. O termo inferncia de tipo bidirecional usado em [38], trabalho que prope um algoritmo para inferncia de tipos no sistema de polimorsmo de rank superior proposto por Odersky e Laufer [37], um dos primeiros trabalhos no sentido de estender HM com polimorsmo de rank superior. O sistema de tipos proposto por Odersky e Laufer, diferentemente do sistema F, admite instanciao de quanticadores que ocorrem no lado esquerdo do construtor funcional (deep instantiation), levando em conta, naturalmente, a contra-varincia deste construtor. O sistema proposto neste trabalho predicativo (variveis quanticadas podem ser instanciadas apenas para tipos monomrcos), o que restringe bastante a sua expressividade. Considere, por Exemplo, a aplicao length ids, onde os tipos de length e ids so: length :: a. [a] Int ids :: [c. c c] Para que a aplicao a aplicao length ids seja bem tipada, a varivel quanticada (a) no tipo de length deve poder ser instanciada para o tipo polimrco c. c c. Outra desvantagem do sistema de Odersky e Laufer requerer anotaes de tipo redundantes e excessivas, problema mais tarde contornado em [38], por meio do mecanismo de propagao de tipos, ou inferncia de tipos bidirecional . O sistema Fn , proposto por Mitchell [36], permite deep instantiation e impredicativo (variveis quanticadas podem ser instanciadas para tipos polimrcos), e atribui tipo a toda expresso bem tipada no sistema F. A vantagem de Fn em relao a F que o primeiro possui a propriedade de tipo principal, o que leva os proponentes deste sistema a argumentar que ele seria, portanto, mais adequado como base para a

26

Captulo 2. Polimorfismo Paramtrico

implementao de polimorsmo de rank superior em linguagens de programao. A inferncia de tipos para Fn , mesmo na presena de anotaes de tipo, entretanto extremamente complicada. O algoritmo de inferncia de tipos apresentado em [11] baseado em Fn , mas entretanto resolve o problema de decidir adequadamente, em todos os casos, quando variveis quanticadas devem ser instanciadas predicativamente ou impredicativamente. Para entender esse problema, considere, por Exemplo a aplicao choose id, onde os tipos de choose e id so: choose :: a. a a a id :: b. b b No sistema HM, o tipo inferido para a expresso (choose id) seria b. (b b) (b b). Entretanto, se o tipo de choose pode ser instanciado impredicativamente, poderamos tambm tipar essa expresso com o tipo (b. b b) (b. b b), e nenhum desses tipos principal (esses dois tipos so incomparveis no sistema F). No sistema MLF, apresentado em [28, 29], o problema de adivinhar quando deve ser feita instanciao predicativa ou impredicativa resolvido estendendo-se a linguagem de tipos do sistema F, de modo a incluir tipos com restries de instanciao. Por Exemplo, nessa linguagem, poderia ser atribudo expresso choose id o tipo principal (a b. b b). a a. Novamente, a inferncia de tipos extremamente complicada, o que motivou a simplicao de MLF proposta em [31, 32], na qual requerida anotao explcita de tipo para todo parmetro de funo com tipo polimrco, sendo essa informao usada para simplicar a inferncia de tipos. Esse ltimo trabalho considera tambm a possibilidade de restringir o sistema, de modo que anotaes de tipo sejam restritas a tipos do sistema F (e no tipos de MLF). Os trabalhos apresentados em [51, 52] tambm buscam contornar esse problema, mas procurando manter a mesma linguagem de tipos do sistema F. No sistema propoto nesses trabalhos FPH o tipo inferido para a aplicao choose id, por Exemplo, seria o tipo principal dessa expresso no sistema HM, ou seja, a. (a a) (a a). O tipo (a. a a) (a. a a) poderia ser inferido apenas no caso de ser provida a anotao explcita de tipo (choose id) :: (a. a a) (a. a a).

2.4

Concluso

Neste Captulo zemos uma reviso sobre sistemas de tipo com suporte a polimorsmo paramtrico, apresentando detalhadamente o sistema de Hindley-Milner, que prov su-

2.4. Concluso

27

porte a polimorsmo de rank-1, e tambm discutimos algumas propostas de extenso a esse sistema no sentido de prover polimorsmo de rank-n. Como vimos, tais extenses possibilitariam a denio de uma funo tal como a funo foo, apresentada no Exemplo 1.1 (3), mediante anotao explcita do tipo do parmetro dessa funo. Considerando o tipo anotado para foo nesse Exemplo, seria vlida, por Exemplo, a aplicao foo reverse. O Captulo 3 apresenta uma extenso do sistema de Hindley Milner para prover suporte a denies sobrecarregadas, a qual baseada no mecanismo de classes de tipos de Haskell. Veremos que essas duas extenses no esto ainda adequadamente integradas: embora sistemas com polimorsmo de rank-n possibilitem denir uma funo com parmetro de tipo polimrco, no possvel aplicar tal funo a um argumento de tipo polimrco restrito, ou seja, a uma expresso cuja denio envolve o uso de algum smbolo sobrecarregado.

Captulo 3 Polimorsmo Restrito: Sobrecarga


O polimorsmo ad hoc, ou polimorsmo de sobrecarga, possibilita prover diferentes denies para um mesmo smbolo (ou varivel), possivelmente com tipos distintos, sendo a denio com o tipo apropriado escolhida de acordo com o contexto no qual o smbolo usado. Em outras palavras, a denio apropriada de uma funo escolhida de acordo com o tipo e a aridade dos argumentos ao qual a funo aplicada ou de acordo com o tipo requerido para o resultado dessa aplicao.1 Note que o polimorsmo de sobrecarga difere do polimorsmo paramtrico discutido anteriormente, no qual uma funo polimrca tem uma denio nica, que opera de maneira uniforme independentemente do tipo da expresso na qual ela usada. A combinao, em uma linguagem de programao, dessas duas formas de polimorsmo paramtrico e de sobrecarga resulta em grande expressividade da linguagem, como veremos em Exemplos apresentados neste captulo. Este captulo apresenta uma extenso do sistema HM para suporte a sobrecarga, baseada no sistemas de classes de tipos de Haskell, que denominamos sistema CTH. Esse sistema uma verso do sistema de tipos qualicados proposto por Mark Jones [19, 15], mas inclui tambm idias propostas em [3, 4]. O sistema CTH constitui a base para a denio do sistema de tipos proposto no captulo 4. A Seo 3.1 prov uma introduo ao sistema de classes de tipos de Haskell. A Seo 3.2 apresenta a sintaxe de tipos e expresses do sistema [3], dorvante denominado CTH e a Seo 3.3 apresenta as regras de derivao de tipos nesse sistema. A inferncia de tipos apresentada na Seo 3.4. A semntica de expresses desse sistema descrita
Algumas linguagens de programao, tais como Java, possibilitam apenas a sobrecarga de smbolos que representam funes, de maneira que a denio apropriada possa ser selecionada de acordo com o tipo e nmero de argumentos ao qual a funo aplicada. Essa estratgia denominada sobrecarga independente de contexto, enquanto que a estratgia adotada em Haskell, mais exvel, denominada dependente de contexto[54].
1

29

30

Captulo 3. Polimorfismo Restrito: Sobrecarga

na Seo 3.4.1.

3.1

Classes de tipos em Haskell

Considere a denio, em Haskell, de uma funo elem que determina se um dado valor elemento de uma lista dada: elem :: Eq a => a -> [a] -> Bool elem y [] = False elem y (x:xs) = y==x || elem y xs Note que essa funo se comporta de maneira uniforme para listas de elementos de qualquer tipo, exceto que denida em termos do teste de igualdade (==), que opera diferentemente para valores de tipos diferentes em outras palavras, (==) um smbolo sobrecarregado. A restrio de tipo Eq a que aparece no tipo dessa funo indica essa dependncia, e restringe a aplicao dessa funo a listas de elementos para os quais a operao (==) denida. Em Haskell, a denio de um smbolo sobrecarregado feita por meio do mecanismo classes de tipos. Esse mecanismo ilustrado por meio do Exemplo a seguir, que apresenta a denio da classe Eq, que dene os tipos dos smbolos (==) e (/=): class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool

A denio do operador (==) para valores de tipos especcos provida por meio da denio de instncias dessa classe. Para tipos bsicos, tais como Int, a denio seria dada em uma denio de instncia tal como a seguir, onde primEqInt o teste de igualdade pr-denido para valores inteiros: instance Eq Int where (==) = primEqInt (a /= b) = not (a == b) A declarao de instncia a seguir exemplica a denio de uma instncia dessa classe para listas (polimrcas):

3.2. Classes, Instncias e Polimorfismo Restrito

31

instance Eq a => Eq [a] where [ ] == [ ] = True (x:xs) == (y:ys) = (x == y) && (xs == ys) Note que, nessa denio, o teste de igualdade para elementos de um tipo arbitrrio, mas xo, usado para denir o teste de igualdade para listas de elementos desse tipo. Em face dessas denies, a operao (==) pode ser usada para comparar listas de inmeros tipos, como por Exemplo [Int], [[Int]], e assim por diante. Uma declarao de classe pode possivelmente incluir restries de classe, como no Exemplo a seguir, estabelecendo desse modo uma hierarquia entre classes: class Eq a => Ord a where (>) :: a -> a -> Bool (>=) :: a -> a -> Bool A restrio de classe Eq a na denio da classe Ord a signica que apenas podem ser denidos como instncias dessa classe tipos que sejam instncia da classe Eq a. O sistema de classes de tipos de Haskell [15] originalmente baseado nos trabalhos propostos em [53, 21]. Outros trabalhos propem extenses a esses primeiros, como a denio de classes de tipos com mltiplos parmetros [25] ou de classes parametrizadas por construtores de tipos [22, 25], a denio de dependncias funcionais [20, 24, 12, 49] ou alternativas para essa proposta [6, 4], ou analisam questes referentes a esses sistemas, tais como a inferncia de tipos [3, 13, 47, 48], o problema de coerncia ou ambiguidade [20, 4], ou abordagens de mundo aberto ou mundo fechado para a denio de instncias de classes [5]. As sees a seguir apresentam um sistema de tipos para suporte a sobrecarga, juntamente com a semntica desse sistema e o algoritmo de inferncia de tipos correspondente. O sistema de tipos aqui apresentado, referenciado como sistema CTH, uma verso baseada nos sistemas apresentados em [21] e [4].

3.2

Classes, Instncias e Polimorsmo Restrito

A Figura 3.1 apresenta a sintaxe livre de contexto de tipos e expresses da linguagem do sistema CTH. Por simplicidade, nesse sistema no consideramos classes parametrizadas por construtores de tipo (e o problema relacionado de inferncia de kind [22]), mas supomos que classes podem ser parametrizadas por mltiplas variveis de tipo. Um programa consiste de declaraes de classe e declaraes de instncia, com

32

Captulo 3. Polimorfismo Restrito: Sobrecarga

Tipos monomcos Tipos com restries Tipos polimrcos Predicado de classes Contexto de predicados Contexto de tipos Contexto de classes

::= a | 1 2 ::= P ::= a.

::= C P, Q ::= | P, c ::= | , (x : ) ::= | c , (class P ) | c , (inst P ) ::= cD; iD; t ::= class P C where x :: ::= instance P C where x = e

Programas p Declarao de classe cD Declarao de instncia iD

Figura 3.1. Sintaxe da linguagem do sistema CTH

escopo global, e de uma expresso, sendo a sintaxe de expresses como no sistema HM. Uma declarao de classe class P C a where {x1 :: 1 ; . . . ; xn :: n } especica o nome (C) e os parmetros (a) da classe, bem como as assinaturas dos smbolos sobrecarregados denidos nessa classe ({x1 :: 1 , . . . , xn :: n }), podendo incluir restries de classe (P ). O tipo especicado para cada smbolo declarado na classe deve incluir todas as variveis que so parmetros da classe. 2 Uma declarao de instncia instance P C where {x1 = e1 ; . . . ; xn = en } especica o nome da classe para a qual a instncia denida (C), assim como os tipos para os quais so instanciados os parmetros da classe ( ), e prov uma denio para cada um dos smbolos sobrecarregados da classe. claro que essa declarao de instncia apenas vlida se existir a declarao correspondente da classe C e i) o cabealho da declarao de instncia (C ) corresponde a uma instanciao do cabealho da classe C (obtida por uma substituio dos parmetros da classe por tipos apropriados); ii) pode-se vericar que a denio provida para cada smbolo da classe tem o tipo apropriado (ou seja, o tipo obtido instanciando-se o tipo provido na assinatura
Algumas restries devem ser impostas s denies de classe, tal como no circularidade da hieraquia de classes, de maneira a garantir decidibilidade da relao de provabilidade de predicados de classe (veja [47, 48]).
2

3.2. Classes, Instncias e Polimorfismo Restrito

33

P |= Q (class Q ) c P |= { }

super

P |= Q (inst Q ) c P |= {}

inst

Figura 3.2. Provabilidade de predicados de classe

desse smbolo conforme denido na declarao de instncia). Um tipo inclui agora um conjunto (possivelmente vazio) de predicados de classe, da forma C , que impem restries sobre os tipos para os quais pode ser instanciado. A meta varivel usada para denotar um predicado de classe; P e Q denotam conjuntos de predicados de classe; escrevemos P, para denotar o conjunto P {} e P, Q para denotar P Q. Um tipo a. P representa o conjunto dos tipos [a ]P [a ] tais que os predicados de classe [a ]P podem ser satisfeitos, isto , |= [a ]P provvel. A relao de provabilidade de predicados P |= Q determinada pelo conjunto de declaraes de classe e declaraes de instncia presentes no programa, de acordo com as regras especicadas na Figura 3.2. Note que a relao P |= Q parametrizada por um contexto de classe c , o qual determinado pelas declaraes de classes e declaraes de instncia presentes no programa, e contm dois tipos de termos:

class P

corresponde primeira linha de uma declarao de classe; cada classe em P uma superclasse da classe nomeada em corresponde primeira linha de uma declarao de instncia; se existe uma instncia de cada classe em P ento existe uma instncia de

inst P

Por Exemplo, as declaraes de classe e de instncia apresentadas no incio desta Seo produzem o contexto de classes c a seguir e introduzem, no contexto de tipos global, digamos 0 , uma atribuio de tipo para cada um dos smbolos sobrecarregados

34

Captulo 3. Polimorfismo Restrito: Sobrecarga

Monotonicidade

(id) (term) (fst) (snd) (univ)

P |= P P |= P, Q |= P P, Q |= Q P |= Q P |= R P |= Q, R

Transitividade

P |= Q Q |= R (trans) P |= R P |= Q S P |= S Q P |= Q P |= Q P, P |= Q, Q P |= Q P, Q |= R P |= R

Fecho

(subs)

Estruturais

(dist)

(cut)

Figura 3.3. Propriedades de P |= Q

declarados nas classes: c = {class Eq a, class {Eq a} Ord a, inst Eq Int, inst {Eq a {Eq [a]} } = {(==) :: a. Eq a a a Bool, (>) :: a. Ord a a a Bool, (>=) :: a. Ord a a a Bool }

A relao de provabilidade de predicados P |= Q satisfaz as propriedades apresentadas na Figura 3.3, conforme denido em [21]. Dado o contexto de classe c acima, seria possvel provar, por Exemplo, |= {Eq [Int]}, usando a regra de transitividade, j que possvel provar, nesse contexto de classe, |= {Eq Int} e {Eq Int} |= {Eq [Int]}, como se mostra a seguir:

3.3. Sistema de Tipos

35

|=

(id)

(inst Eq Int) c |= {Eq Int}


(id)

(inst)

{Eq a} |= {Eq a} (inst {Eq a} Eq [a]) c {Eq a} |= {Eq [a]} (subs) {Eq Int} |= {Eq [Int]}

(inst)

3.3

Sistema de Tipos

O sistema de tipos CTH apresentado na Figura 3.4, na forma de regras para julgamentos da forma P; t : signicando que o tipo pode ser atribudo ao termo t em um contexto de tipo , se os predicados de classe P podem ser satisfeitos. Para maior brevidade, optamos por apresentar o sistema diretamente em uma verso dirigida por sintaxe, que ser mais til para a posterior denio da inferncia de tipos. As regras de derivao de tipos so semelhantes s do sistema HM, mas requerido aqui um tratamento apropriado do contexto de predicados de classe. Na regra (APP), os predicados de classe que restringem tanto o tipo da funo (t) como o tipo do argumento (u) devem ser considerados como restries sobre o tipo da aplicao (t u). Na regra de generalizao, os predicados de classe P requeridos na derivao de tipo P ; t : so movidos do contexto de predicados de classe para o tipo, e as variveis livres do tipo resultante P so quanticadas. A instanciao restringida pelos predicados de classe do tipo, em conformidade com a relao de derivabilidade de predicados P |= Q. Por, Exemplo, no contexto de classes c , o tipo a. Eq a a a pode ser instanciado, por Exemplo, para [Int] [Int] por meio da substituio [a [Int]], j que |= Eq [Int], como provamos anteriormente. A restrio imposta na derivao do julgamento ; t : usada para evitar a derivao de tipos ambguos. Para entender essa noo de ambiguidade, considere as seguintes denies de classe, que especicam os tipos das funes sobrecarregadas show e read, para converso de valores de um determinado tipo a em um valor de tipo String e vice-versa, respectivamente:

36

Captulo 3. Polimorfismo Restrito: Sobrecarga

P;
inst

t:
(VAR)

P P ; , (x : ) x :

P ; , (x : ) t : P ; x. t :

(ABS)

P; t : Q; u : P, Q; t u : t: P P ; (t :: ) :
inst

(APP)

gen u : P ; , (x : ) t : P ; let x = u in t :

gen

(LET)

(ANNOT)

gen

t:

inst

P; t : f tv(P P | tv( ) ) = f a = f tv(P ) f tv() gen t : a. P

(GEN)

inst

Q |= [a ]P (a. P ) (Q [a ] )

(INST)

Figura 3.4. Sistema de tipos CTH

class Show a where show :: a String class Read a where read :: String a Na presena dessas declaraes de classe, possvel derivar para show e read os tipos: show :: read :: (Show a) a String (Read a) String a

Nesse contexto seria possvel derivar para a expresso \x > show(read x) o tipo a. (Show a,Read a) String String. Entretanto, esse termo ambguo, pois no seria possvel determinar quais as instncias (ou denies) de read e show deveriam ser usadas nesse caso; o tipo a. (Show a,Read a) String String tambm dito ambguo. A derivao de tipos ambguos pode ser evitada impondo-se uma restrio sin-

3.4. Inferncia de Tipos

37

ttica apropriada sobre os tipos derivveis no sistema de tipos. Para sistemas com suporte a classes de tipos com mltiplos parmetros essa restrio pode ser expressa como no sistema de tipos CTH, tendo sido essa restrio originalmente proposta em [3]. Informalmente, um tipo a. P ambguo se existe alguma varivel em P que no atingvel a partir do conjunto de variveis de . Uma varivel a de P atingvel a partir de um conjunto de variveis V se a V ou a ocorre em algum predicado P que contm uma varivel atingvel a partir de V . Uma restrio atingvel a partir de V se contm alguma varivel atingvel a partir de V . Essa noo formalizada por meio da operao P | , denida na Figura 3.5. V

P |V = {C P | f tv( ) V = } P | = V P |V P | tv(P |V ) f if f tv(P |V ) V otherwise

Figura 3.5. Restries de P atingveis a partir de V

3.4

Inferncia de Tipos

O algoritmo de inferncia de tipos para o sistema CTH apresentado na Figura 3.6. O algoritmo de inferncia de tipos apresentado na forma de um conjunto de regras de derivao para julgamentos da forma P; t : (, P , )

signicando que a tipagem (P , , ) inferida para o termo t no contexto de tipos , e em presena das restries determinadas pelo contexto de predicados de classe P . O algoritmo de inferncia de tipos essencialmente o mesmo que para o sistema HM, exceto pelo tratamento dos contextos de predicados de classe. Na regra da aplicao, o contexto de predicados inferido para a aplicao (t u) obtido pela unio dos contextos de predicados de classe usados na inferncia de tipos para t e para u. Para entender a razo disso, considere a inferncia de tipos para a aplicao (t u), em um contexto , onde = {t : a. (T a) (a Int) a, u :

38

Captulo 3. Polimorfismo Restrito: Sobrecarga

P;
inst

t : (, P , )
(VAR)

P P ; , (x : ) x : (, P, )

P ; x , (x : a) t : (, P , ) a fresh P ; x. t : ( (x) , P , [x,] )


gen

(ABS)

P ; t : (1 , P1 , 1 ) P ; 1 u : (2 , P2 , 2 ) S = unify(1 = 2 a) a fresh P ; t u : (Sa, S(P1 , P2 ), S2 ) t : ( , ) inst P P ; (t :: ) : (, P , )


sh

(APP)

gen

u : (, ) P ; x , (x : ) t : (, P , ) P ; let x = u in t : (, P , [x,] )

(LET)

(ANNOT)

gen

t : (, )

inst

P ; t : (, Q, ) f tv(Q Q | tv( ) ) = f a = f tv(Q ) f tv( ) gen t : (a. Q , )

Q |= [a b]P b fresh
(GEN) (INST) inst

a. P Q [a b]

sh

)
(SH)

S = match( Q |= SP b fresh
sh

a. P b. Q

Figura 3.6. Inferncia de tipos para CTH

a. (U a) a a} e um contexto de predicados vazio, a qual apresentada a seguir:


inst

a. (T a) (a Int) a (T a1 ) (a1 Int) a1 (T a1 ); t : ((a1 Int) a1 , (T a1 ), )


inst

(VAR)

a. (U a) a a (U a2 ) a2 a2 (U a2 ); u : (a2 a2 , (U a2 ), )

(VAR)

S = unify((a1 Int) a1 = (a2 a2 ) a) ; (t u) : (Int, (G Int, O Int), )

a fresh
(APP)

3.4. Inferncia de Tipos

39

As regras que denem a relao de ordem em tipos polimrcos sh so tambm modicadas levando em conta a relao de provabilidade de predicados. Note que as relaes inst e sh so implicitamente parametrizadas pelo contexto de classe c , j que este induz a relao P |= Q. Para que o sistema apresentado na Figura 3.6 seja de fato um algoritmo, deve ser ainda denido um algoritmo para implementao da relao de provabilidade de predicados P |= Q. Vamos omitir aqui a denio desse algoritmo, remetendo o leitor interessado aos trabalhos apresentados, por Exemplo, em [4, 48]. preciso aqui observar que, para que tal algoritmo exista, isto , para que a relao P |= Q seja decidvel, necessrio impor restries apropriadas sobre a forma das declaraes de classes e declaraes de instncias, uma vez que a relao P |= Q, para predicados de classe arbitrrios, indecidvel (veja [47]). O algortimo apresentado na Figura 3.6 correto em relao ao sistema de tipos CTH e infere tipos principais para termos desse sistema. Essas propriedades so expressas formalmente pelos teoremas a seguir, cujas provas podem ser encontradas em [21].

Teorema 3.4.1 (Correo) Se P ;

t : (, P , ) ento P ;

t:

Teorema 3.4.2 (Tipo Principal) Para todo termo t, se P ; P ; gen t : ( , ) , onde sh e sh .

gen

t : , ento

3.4.1

Semntica

A semntica de classes de tipos de Haskell pode ser denida no chamado estilo de passagem de dicionrio proposto por Wadler e Blott [53], e que constitui um caso particular da semntica para sistemas de tipos com predicados denida por Mark Jones em [21]. Para compreender essa idia considere novamente as seguintes declaraes de classe e de instncia, apresentadas anteriormente na introduo desta Seo: class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool

40

Captulo 3. Polimorfismo Restrito: Sobrecarga

class Eq a => Ord a where (>) :: a -> a -> Bool (>=) :: a -> a -> Bool instance Eq Int where i1 == i2 = primEqInt i1 i2 i1 /= i2 = not (i1 == i2) instance (Eq a) => Eq [] == [] (x:xs) == (y:ys) xs /= ys [a] where = True = (x == y) && (xs == ys) = not (xs == ys)

elem :: Eq a => a -> [a] -> Bool elem x [] = False elem x (y:ys) | x==y = True | otherwise = elem x ys Informalmente, a semntica de passagem de dicionrio pode ser compreendida do seguinte modo:

uma denio de uma classe C traduzida como um tipo polimrco de um dicionrio que contm denies de smbolos cuja assinatura especicada nessa classe, sendo os parmetros desse tipo exatamente os parmetros da classe;

uma declarao de instncia da classe C traduzida como valor de uma instncia do tipo do dicionrio de C, o qual contm denies especcas para cada smbolo sobrecarregdo da classe C;

uma expresso que envolve um smbolo sobrecarregada denido em uma classe C traduzida como uma funo que tem um parmetro adicional, cujo tipo o tipo do dicionrio dessa classe.

De acordo com essa semntica, as declaraes apresentadas acima, por Exemplo, poderiam ser traduzidas do seguinte modo:

3.5. Concluso

41

tipo do dicionrio da classe Eq data Eq a = DEq {(==)::(a->a->Bool), (/=)::(a->a->Bool)} tipo do dicionrio da classe Ord data Ord a = DOrd {dEq::Eq a, (>)::a->a->Bool, (>=)::a->a->Bool}

dicionrio correspondente a instncia Eq Int dEqInt :: Eq Int dEqInt = DEq {(==) = primEqInt, (/=) = \ x y -> not (x == y)} dicionrio correspondente dEqList :: Eq a -> Eq [a] dEqList d = DEq {(==) = el, where el [] [] = el (x:xs) (y:ys) = el _ _ = a instncia Eq [a] (/=) = \ x y -> not (el x y)} True d.(==) x y && el xs ys False

dicionrio correspondente instncia Ord Int dOrdInt :: Ord Int dOrdInt = DOrd {dEq = dEqInt, (>) = primGtInt, (>=) = \ x y -> (x primGtInt y) || (dEq.(==) x y)} elem tem como parmetro adicional um dicionrio da classe Eq elem :: Eq a => a -> [a] -> Bool elem d x [] = False elem d x (y:ys) | d.(==) x y = True | otherwise = elem d x ys Uma denio formal da semntica de expresses do sistema CTH pode ser encontrada em [21, 15], onde a semntica denida na forma de uma traduo (dirigida por sintaxe) de expresses do sistema CTH para expresses bem tipadas do sistema F.

3.5

Concluso

Este Captulo apresentou uma reviso sobre o mecanismo de suporte a sobrecarga baseado de Haskell, em classes de tipos, apresentado um sistema de tipos que formaliza esse mecanismo, o algoritmo de inferncia de tipos correspondente e a semntica de

42

Captulo 3. Polimorfismo Restrito: Sobrecarga

expresses nesse sistema de tipos, denida no estilo de passagem de dicionrio. Nesse sistema, possvel denir, por Exemplo, uma funo sort, para ordenar elementos de uma lista (digamos em ordem no decrescente), com tipo sort :: a. (Ord a) [a] [a], signicando que tal funo pode ser aplicada a listas de elementos de qualquer tipo a que seja instncia da classe Ord, ou seja, qualquer tipo a para o qual as relaes de comparao (>) e (>=) sejam denidas. Fazendo uso mais uma vez do Exemplo 1.1 (3), seria bastante razovel esperar que fosse vlida a aplicao foo sort, resultando no valor ([False,True],[a,b,c]). Essa aplicao entretanto no vlida, mesmo em uma linguagem com suporte para sobrecarga e para polimorsmo de rank superior, pois essas duas extenses do sistema HM no esto integradas. Note que o tipo de sort igual ao do parmetro de foo, a menos da restrio de classe no tipo do primeiro. do nosso conhecimento apenas um trabalho que busca resolver essa questo, possibilitando a aplicao de uma funo com parmetro de tipo polimrco a uma expresso de tipo polimrco restrito: o sistema QMLF, proposto em [33]. Nesse sistema, possvel, por Exemplo, anotar para foo o tipo: foo :: (a. Ord a [a] [a]) ([Bool], [Char]) Essa anotao de tipo possibilita tanto a aplicao foo sort, como a aplicao foo reverse, j que, no sistema QMLF, o tipo de reverse, qual seja, reverse :: a. [a] [a], pode ser para o tipo polimrco restrito a. (Ord a) [a] [a]. Entretanto, a anotao de tipo acima apenas possibilita aplicar foo a um argumento de tipo a. [a] [a] ou a. (Ord a) [a] [a], no sendo possvel, por Exemplo, a aplicao de foo a um argumento de tipo a. (C a) [a] [a], onde C uma classe distinta de Ord. As questes que buscamos responder neste trabalho podem ser expressas do seguinte modo: Que forma anotao de tipo poderia ser provida de modo a permitir a denio de funes tais como foo, em que o parmetro usado polimorcamente no corpo da funo, possibilitando o reuso de tais funes em diferentes contextos? Como denir um sistema de tipos em que tal anotao de tipo possa ser especicada? Como denir a semntica e a inferncia de tipos para expresses desse sistema? Nossa resposta para essas questes apresentada no Captulo 4 a seguir.

Captulo 4 Funes Polimrcas Restritas de Primeira Classe


Este captulo apresenta a denio de uma extenso do sistema de suporte a sobrecarga CTH, apresentado no captulo 3. Essa extenso doravante denominada CTi possibilita a denio de funes com parmetros de tipo polimrco, mediante anotao explcita do tipo de tais funes pelo programador, sendo esses tipos especicados na forma de tipos interseo. No sistema proposto, funes com parmetros polimrcos podem tanto ser aplicadas a argumentos de tipo polimrco paramtrico (como em sistemas de polimorsmo de rank superior), como a argumentos de tipo polimrco restrito, promovendo valores sobrecarregados a objetos de primeira classe. A Seo 4.1 rev a motivao para o sistema CTi e descreve intuitivamente as idias bsicas desse sistema. A Seo 4.2 apresenta a sintaxe de tipos e expresses do sistema CTi, sendo as regras de derivao de tipos nesse sistema apresentadas na Seo 4.3. A inferncia de tipos apresentada na Seo 4.4.

4.1

Introduo

Como poderia ser especicado o tipo de uma funo cujo argumento usado polimorcamente no corpo da sua denio? Naturalmente, cada argumento usado no corpo de uma funo apenas um nmero nito de vezes, e gostaramos de permitir que em cada uso o seu tipo pudesse ser diferente, desde que, em cada caso, o tipo com que o argumento usado seja uma instncia do tipo especicado para esse argumento na anotao de tipo. O uso de uma tipo interseo nos parece natural para expressar esse requerimento. Tipos interseo foram propostos por Coppo, Dezani-Ciancaglini e Venneri [8], 43

44

Captulo 4. Funes Polimrficas Restritas de Primeira Classe

como uma alternativa ao sistema HM para estender o lambda-calculus tipado simples, utilizando polimorsmo nitrio em lugar de polimorsmo innitrio, ou universal, como no sistema HM. Os dois sistemas no so equivalentes. Existem expresses que no podem ser tipadas em HM e que podem ser tipadas em um sistema de tipos interseo e vice-versa. Por exemplo, a expresso x. xx, qual pode ser atribudo o tipo (a (a b)) b. Por outro lado, em um sistema de tipos interseo no possvel expressar, por exemplo, um tipo para o operador de igualdade entre listas, de modo que esse operador possa ser usado para comparar listas de elementos de um tipo qualquer, o que possvel em uma extenso do sistema HM com polimorsmo restrito, tal como explicado anteriormente. Diferentemente de sistemas usuais de tipos interseo, no sistema de tipos denido neste trabalho no se pretende utilizar polimorsmo nitrio em lugar de polimorsmo innitrio. Ao contrrio, o sistema aqui proposto busca manter mantm total compatibilidade com o sistema HM na ausncia de anotaes de tipo, utilizando tipos interseo apenas para estender HM de maneira que seja possvel denir funes nas quais o parmetro usado com diferentes tipos no corpo da funo. Nesse caso, requerida uma anotao explcita do tipo desse parmetro na denio da funo. Intuitivamente, um valor de tipo interseo 1 2 visto como uma valor que representa objetos de tipo 1 e de tipo 2 . Sendo assim, sistemas de tipo interseo incluem as seguintes regras genricas de introduo (generalizao) e eliminao (instanciao) de tipos interseo: t : 1 t : 2 t : 1 2
(GENi)

t : 1 2 t : 1

(INSTi)

t : 1 2 t : 2

(INSTi)

Sistemas de tipo polimrcos podem ser denidos de forma dirigida por sintaxe, restringindo-se a instanciao de tipos polimrcos regra (VAR) e a generalizao regra (LET). Em um sistema genrico de tipos interseo, seria necessrio a introduo de tipos interseo na concluso de cada regra assim como eliminao de tipos interseo em cada uma das premissas da regra. Isso resulta em enorme complexidade da inferncia de tipos. Por esse motivo, assim como em outros sistemas de tipo interseo [27, 9], no sistema proposto neste trabalho tipos interseo no podem ocorrer do lado direto do construtor de tipos funcional (), podendo ocorrer apenas como tipos de parmetros de lambda-abstraes. Mediante essa restrio, possvel limitar a introduo de tipos interseo apenas regra da aplicao, usando a introduo de interseo para obter o tipo do argumento, quando o tipo do parmetro da funo um tipo interseo. Dualmente, a eliminao de tipo interseo ca restrita regra (VAR), sendo isso requerido para derivar um tipo monomrco a partir de um tipo interseo

4.2. Sintaxe

45

exsitente no contexto de tipos, o qual corresponde a uma anotao explcita de tipo interseo para o parmetro de uma funo. Mesmo impondo a restrio de que tipos interseo no podem ocorrer do lado direito do construtor de tipos funcionais, a inferncia de tipos em um sistema de tipos interseo extremamente complexa (veja, por exemplo, [27]). Essa complexidade menor no sistema CTi, uma vez que tipos interseo apenas so introduzidos por meio de anotaes de tipo explcitas. O sistema de tipos proposto neste trabalho combina de maneira original tipos polimrcos (tanto paramtricos como restritos por predicados de classe) e tipos interseo, usando estes ltimos apenas para possibilitar a denio de funes em que o parmetro usado com tipos distintos no corpo da sua denio. Como mencionamos na introduo desse trabalho, no sistema CTi possvel denir a funo foo do exemplo 1.1 (3), provendo, por exemplo, a anotao de tipo foo :: a, b. ([Bool] a [Char] b) (a, b) Essa anotao de tipo sucientemente expressiva para possibilitar a aplicao de foo a qualquer dos argumentos considerados anteriormente (seja aqueles com tipo polimrco paramtrico ou com tipo polimrco restrito), em geral a qualquer expresso cujo tipo possa ser instanciado tanto para [Bool] a como para [Char] b.

4.2

Sintaxe

A linguagem de tipos e expresses do sistema CTi apresentada na Figura 4.1. Parmetros de funes podem ser agora uma interseo de tipos monomrcos (veja a denio de tipos denotados pela metavarivel ). Escrevemos para representar um tipo interseo (1 . . . n ), para n 1, e supomos que o construtor de tipos interseo () satisfaz as seguintes propriedades: Idempotncia Comutatividade Associatividade = 1 2 = 2 1 1 (2 3 ) = (1 2 ) 3

Escrevemos (1 . . . n ) se = i para algum 1 i n e (1 . . . n ) se implica (1 . . . n ). A denio de f tv(), que computa as variveis livres de um tipo , naturalmente estendida de modo a levar em conta tipos interseo, denindo-se que f tv(1

46

Captulo 4. Funes Polimrficas Restritas de Primeira Classe

Tipos Tipos interseo Tipos com restries Tipos polimrcos Predicado de classes Contexto de predicados Contexto de tipos Contexto de classes

::= ::= ::= ::=

a | P a. C , | P, | , x : | , (x : ) | c , (class P ) | c , (inst P ) cD; iD; t class P C where x :: instance P C where x = e

::= P, Q ::= c ::= ::= ::= ::= ::=

Programas p Declarao de classe cD Declarao de instncia iD Termos t, u ::= | | | | |

x Varivel x. t Abstrao funcional (x :: ). t Abstrao com anotao de tipo interseo tu Aplicao let x = u in t Denio local t :: Anotao de tipo ( fechado)

Figura 4.1. Sintaxe da linguagem do sistema CTi

. . .n ) = f tv(1 ). . .f tv(1 ). A aplicao de substituio [a ] tambm estendida apropriadamente, denindo-se [a ](1 . . . n ) = [a ]1 . . . [a ]n . Tal como no sistema CTH (veja 3.1), um programa consiste de declaraes de classe e declaraes de instncia, seguidas de uma expresso. Tipos polimrcos podem incluir um conjunto (possivelmente vazio) de restries, na forma de predicados de classe, e um tipo funcional pode ter, do lado esquerdo de (), um tipo interseo. Expresses so tambm como no sistema CTH exceto que agora consideramos tambm lambda-abstraes com anotao explcita do tipo do parmetro, na forma (x : ). t. Note que um contexto de tipos () pode conter tanto tipos polimrcos (), como tipos interseo ().

4.3. Sistema de Tipos

47

4.3

Sistema de Tipos

O sistema de tipos CTi apresentado na Figura 4.2, na forma dirigida por sintaxe, sendo denido como um conjunto de regras de derivao para julgamentos da forma P; t:

signicando que o tipo pode ser atribudo ao termo t em um contexto de tipos , se os predicados de classe P podem ser satisfeitos. Como no sistema CTH (veja 3.4), a derivao de tipos parametrizada pela relao de prova de predicados de classe P |= Q, induzida pelas declaraes de classe e declaraes de instncia presentes no programa. O sistema de tipos CTi difere do sistema CTH apenas nas regras (ABSA), (APP) e (VAR). A regra (ABSA) dene a derivao de tipos para uma lambda-abstrao com anotao explcita do tipo do parmetro, de maneira semelhante regra (ABS). A regra (APP) deve considerar agora duas possibilidades inexistentes no sistema CTH, para uma aplicao (t u): A possibilidade do tipo do parmetro da funo (f ) ser um tipo interseo ( ). Nesse caso, o tipo do argumento (u) deve poder ser promovido para ( ), o que signica que o tipo de (u) deve poder ser instanciado para cada um dos tipos . A possibilidade de ser necessria uma eliminao de tipo interseo, para obteno do tipo da funo (t). Isso ocorre apenas se a aplicao (t u) ocorre no corpo de uma funo, e t um parmetro dessa funo, cujo tipo uma interseo ( ). Portanto, nesse caso, t uma varivel, sendo o tipo de t obtido diretamente a partir do contexto de tipos. O primeiro caso acima tratado por meio do julgamento de tipo auxiliar P;
I

t:

que promove o tipo do argumento para um tipo interseo, se for o caso, usando introduo de tipo interseo. O segundo caso tratado por meio do julgamento P ; E t : As demais regras de derivao so tais como no sistema CTH, sendo tambm como anteriormente as regras para derivao dos julgamentos gen t : , inst e

48

Captulo 4. Funes Polimrficas Restritas de Primeira Classe

P; P P ; , (x : ) x : P ; , (x : ) t : P ; x. t :
inst (VAR)

t:

(ABS)

P ; , (x : ) t : P ; (x :: ). t :

(ABSA)

P ; E t : Q; I u : P, Q; t u : gen u : P ; , (x : ) t : P ; let x = u in t :

(APP)

(LET)

t: P P ; (t :: ) :
inst

gen

(ANNOT)

gen

t:

inst

P; t : f tv(P P | tv( ) ) = f a = f tv(P ) f tv() gen t : a. P

(GEN)

inst

Q |= [a ]P a. P Q [a ]

(INST)

P; P; P; t: t:
(ID)

t:
(GENi)

Pi ; t : i , para i = 1, . . . , n (P1 , . . . , Pn ); I t : 1 . . . n P;
E

t: P; P; x: x:
(ID)

1in P ; , (x : 1 . . . n )

(INSTi)

x : i

Figura 4.2. Sistema de tipos CTi

: ) (veja Figura 3.4). Para melhor compreender as regras de derivao do sistema CTi, considere a derivao de tipo para a aplicao foo sort, sendo foo a funo denida no exemplo 1.1

sh

4.3. Sistema de Tipos

49

(3), em um contexto , em que os tipos de foo e de sort so: foo = a, b. ([Bool] a [Char] b) (a, b) sort = sort :: a. (Ord a) [a] [a] Na regra (APP), a descrio do tipo da funo foo como a seguir:
foo (([Bool] [Bool]) ([Char] [Char])) ([Bool], [Char]) ; , (foo : foo ) foo : (([Bool] [Bool]) ([Char] [Char])) ([Bool], [Char]) ; , E foo : (([Bool] [Bool]) ([Char] [Char])) ([Bool], [Char])
inst (VAR) (ID)

O tipo de sort promovido para o tipo (([Bool] [Bool]) ([Char] [Char])), por meio da derivao de tipo a seguir:
sort (Ord [Bool]) [Bool] [Bool] (Ord [Bool]); , (sort : sort ) sort : [Bool] [Bool] sort (Ord [Char]) [Char] [Char] (Ord [Char]); , (sort : sort ) sort : [Char] [Char] (Ord [Bool],Ord [Char]);
I inst inst (VAR)

(VAR)

sort : ([Bool] [Bool]) ([Char] [Char])

(GENi)

Usando as concluses das derivaes acima, obtemos nalmente, na regra (APP):


;
E

foo : (([Bool] [Bool]) ([Char] [Char])) ([Bool], [Char])


I

(Ord [Bool],Ord [Char]);

sort : (([Bool] [Bool]) ([Char] [Char])) foo sort : ([Bool],[Char])


(APP)

(Ord [Bool],Ord [Char]);

O tipo derivado para foo sort ([Bool],[Char]), devendo ser observado que, nessa derivao de tipos, o contexto de classe c deve ser tal que a relao de provabilidade de predicados induzida por esse contexto prova |= {Ord [Bool]} e |= {Ord [Char]}. Considere agora a derivao do tipo de g na aplicao g [True,False], no corpo da funo foo. O tipo de g derivado do seguinte modo:
(GENi)

; , (g : g )

(INSTi)

g : [Bool] a

Considere ainda uma expresso da forma \(x :: ). t, para a qual ( ) consiste na conjuno de dois tipos, tais como, por exemplo, 1 e 2 e tal que o parmetro (x) aplicado a um argumento de tipo , no corpo (t) dessa funo. Nesse caso, existem duas possveis escolhas para o tipo do parmetro (x) quando usado nessa aplicao: 1 ou 2 ; isso signica que seria possvel derivar tanto o tipo 1 como 2

50

Captulo 4. Funes Polimrficas Restritas de Primeira Classe

para essa aplicao. Isso caracteriza uma situao de ambiguidade: no seria possvel determinar qual das implementaes ligadas a x deveria ser usada nessa aplicao a implementao de tipo 1 ou a implementao de tipo 2 . Veremos, na Seo 4.4, que possvel detectar essa situao de ambiguidade na inferncia de tipos, podendo ser reportada, nesse caso, uma mensagem de erro de anotao de tipo ambguo. claro que no possvel obter uma derivao de tipo para uma funo da forma \(x :: ). t, se o parmetro x usado no corpo da funo com algum tipo (monomrco) que no ocorre em ( ). Por outro lado, as regras do sistema de tipos no impedem que uma anotao ( ) inclua algum tipo que no corresponde a nenhum dos usos do parmetro x no corpo da funo. Pode ser interessante tambm considerar invlidas anotaes de tipo tais como essa, mas para isso o sistema de tipos teria que ser modicado de modo a propagar, ao longo das derivaes de tipo, alguma informao sobre os tipos de cada um dos usos, no corpo de uma funo, para um parmetro dessa funo que tenha tipo interseo.

4.4

Inferncia de Tipos

O algoritmo de inferncia de tipos para CTi apresentado na Figura 4.3. Ele semelhante ao algoritmo de inferncia de tipos para o sistema CTH (veja Figura 3.6), diferindo entretanto nas regras (ABSA), (APP) e (VAR), tal como ocorre para o sistema de tipos. No algoritmo de inferncia de tipos existem duas regras para inferncia de tipos para uma aplicao (t u), correspondendo aos seguintes possveis casos, que devem ser considerados: A regra (APP1) usada no caso em que o termo t uma varivel (x). Nesse caso necessrio considerar a possibilidade de que o tipo de t seja um tipo interseo, o que possvel j que tipos interseo podem ocorrer no contexto de tipos. Se for esse o caso, esse tipo interseo deve ser eliminado, de maneira apropriada, selecionando-se um dentre os tipos que constituem essa interseo. Essa seleo realizada conforme o tipo do argumento da aplicao, sendo por essa razo necessrio inferir primeiro o tipo do argumento, e depois o tipo da funo, nessa forma da regra da aplicao. Se nenhum, ou mais de um, dentre os tipos que compem o tipo interseo da funo puder ser selecionado, conforme requerido pelo tipo do argumento, reportado um erro de tipo. Portanto, na inferncia de tipos possvel detectar uma situao de uso ambguo de um

4.4. Inferncia de Tipos

51

P;
inst

t : (, P , )
(VAR)

P P ; , (x : ) x : (, P , )

P ; , (x : a) t : (, P , ) a fresh P ; x. t : ( (x) , P , [x,] ) P ; , (x : ) t : (, P , ) a fresh P ; (x :: ). t : ( , P , [x,] ) P ; u : (, P2 , 2 ) P ; 2 E [ ]x : (P1 , 1 , S, ) P ; x u : ( , (P 1, SP2 ), 1 )

(ABS)

(ABSA)

(APP1)

P ; t : (1 , P1 , 1 ) S = unify(1 = a b) a,b fresh P ; 1 I [S a] u : (P2 , 2 , S) P ; t u : (SS b, (SP 1, P2 ), 2 )

(APP2)

; u : (, ) P ; x , (x : ) t : (, P , ) P ; let x = u in t : (, P , [x,] ) P;
gen

gen

(LET)

P ; gen t : ( , , ) sh inst P P ; (t :: ) : (, P , )
inst

(ANNOT)

t : (, )

P ; t : (, Q, ) f tv(Q Q | tv( ) ) = f a = f tv(Q ) f tv( ) P ; gen t : (a. Q , )

Q |= [a b]P b fresh
(GEN) (INST) inst

a. P Q [a b]

sh

S = match( ) Q |= SP b fresh
(SH) sh

a. P b. Q

Figura 4.3. Inferncia de tipos para CTi

52

Captulo 4. Funes Polimrficas Restritas de Primeira Classe

parmetro de tipo interseo no corpo da funo, que corresponde ao caso em que possvel mais de uma escolha dentre os tipos que ocorrem na interseo. Essa situao tratada por meio do julgamento de inferncia de tipo auxiliar P ; 2 E [ ]x : (P1 , 1 , S, ). A regra (APP2) corresponde ao caso em que o termo t no uma varivel. Nesse caso, deve ser considerada a possibilidade de que o tipo de t seja da forma , o que requer vericar se o tipo do argumento pode ser promovido para o tipo . Portanto, nessa forma da regra da aplicao, o tipo da funo deve ser inferido primeiro, sendo usado para guiar a inferncia do tipo do argumento. Essa situao tratada por meio do julgamento auxiliar de inferncia de tipos P ; I []t : (P , , S). Note que a escolha dentre as duas possveis regras de inferncia de tipo para uma aplicao determinada pela forma sinttica do termo que corresponde funo. O julgamento auxiliar de inferncia de tipo P;
I

[]t : (P , , S)

signica que se pode vericar que o tipo inferido para t no contexto P ; , digamos , pode ser usado em um contexto que requer um valor de tipo , isto , unica com , ou pode ser promovido para o tipo , quando um tipo interseo da forma . As regras para derivao desse julgamento so apresentadas na Figura 4.4, sendo que a regra a ser usada determinada pela forma sinttica do tipo . O julgamento da forma P;
E

[ ] x : (P, , S, )

corresponde aos dois possveis casos da regra de instanciao do sistema de tipos. Nesse julgamento, o tipo inferido para o parmetro ao qual x deve ser aplicado, sendo ( , P, ) a tipagem inferida para o resultado dessa aplicao, em um contexto P ; . As regras para derivao desse julgamento so apresentadas na Figura 4.5. Note que a regra (INSTi) usa match, e no unicao: o objetivo selecionar, dentre os tipos componentes do tipo interseo, aquele que pode ser usado como tipo da funo em uma aplicao a um argumento de tipo ( ). A funo match pode ser denida em termos da unicao: match(1 2 ) = unify(1 = [a cK ]2 ) onde a = f tv(2 ) e cK so novas constantes de Skolem

4.4. Inferncia de Tipos

53

P;

[] t : (P, , S)

P ; t : ( , P , ) S = match( = ) a fresh P ; I [ ] t : (SP , S , S)

(GENi1)

S0 = id; 0 = ; P0 = para i = 1..n P ; Si1 i1 t : (i , Qi , i ) Si = unify(i = i ) Si1 Pi = Si Qi , Pi1 I P; [1 . . . n ] t : (Sn Pn , n , Sn )

(GENi2)

Figura 4.4. Inferncia de tipo da aplicao, dirigida pelo tipo da funo

P;

[ ] x : (P, , S, )

(x : ) let R = {(S, a) | S = match( a ), , a fresh} in {(S, a)} = R P ; E [ ] t : (, , S, Sa) P ; x : ( , P , ) S = unify( = a) a fresh P ; E [ ] x : (P , S , S, Sa)

(INSTi)

(INST)

Figura 4.5. Inferncia de tipo da aplicao, dirigida pelo tipo do argumento

Um prottipo desse algoritmo de inferncia de tipos foi implementado na linguagem Haskell, para um subconjunto de expresses nessa linguagem. Essa implementao baseada na implementao do sistema de sobrecarga de Haskell descrito em [23] e descrita na seo a seguir. Embora no tenhamos ainda uma prova formal das propriedades de correo e de tipo principal para o algoritmo de inferncia de tipos proposto acima, temos forte convico da validade dessas propriedades, exceto para o caso de anotaes de tipo

54

Captulo 4. Funes Polimrficas Restritas de Primeira Classe

interseo em parmetros de funo, exceto no caso em que tal anotao tal que um dos usos do parmetro no corpo da funo corresponde a mais de um dos tipos que compem o tipo anotado. Esse caso tratado adequadamente na inferncia de tipos, no sendo permitido, j que corresponde a uma ambiguidade, mas permitido no sistema de tipos. A similaridade entre os sistemas de tipo CTi e CTH, e os testes realizados com o prottipo implementado, nos permitem formular as seguintes conjecturas em relao s propriedades de correo e inferncia de tipos do algoritmo apresentado neste trabalho (excetuando-se o caso de expresses com anotao de tipo tal como mencionado acima). Conjectura 4.4.1 (Correo) Para todo termo t, se P ; t : (, P , ) ento P ; t : (exceto se t uma funo com anotao de tipo interseo em que um dos usos do parmetro no corpo da funo corresponde a mais de um tipo includo no tipo interseo anotado, caso em que existe a derivao de tipo no sistema, mas o algoritmo detecta, corretamente, erro de tipo). Conjectura 4.4.2 (Tipo Principal) Para todo termo t, se P ; P ; gen t : ( , ) , onde sh , e sh .
gen

t : , ento

4.5

Implementao

A implementao da inferncia de tipos para o sistema CTi foi baseada em uma implementao do sistema descrito em [4] e na implementao descrita por Mark P. Jones em [23]. Esse cdigo est que est disponvel em https://github.com/rodrigogribeiro/ core/tree/typeinference e o cdigo da implementao da inferncia de tipos para CTi aqui descrita est disponvel em https://github.com/emcardoso/CTi. A inferncia de tipos implementada sobre uma linguagem ncleo, para a qual traduzido um programa escrito na linguagem Haskell original. A representao de tipos nessa linguagem ncleo foi modicada, de modo a incluir tambm uma representao apropriada para tipos interseo. Tipos interseo so representados como uma lista de tipos. Como vimos, no sistema CTi tipos interseo apenas podem ser introduzidos por meio de anotaes de tipos, e apenas podem ocorrer em parmetros de funes. A informao provida pela anotao de tipo deve ser usada para guiar o processo de inferncia de tipos. Em virtude disso, necessrio modicar o mtodo tradicional de inferncia de tipos, de modo a propagar a informao provida pela anotao de tipo ao longo do cdigo do programa, usando usa essa informao quando necessrio. Considere o seguinte exemplo:

4.5. Implementao

55

f :: (Int -> Int) -> (Int,Int) f g = (g 1, g 2) Na inferncia de tipos tradicional, o tipo (do corpo) de f inferido e verica-se se o tipo anotado uma instncia do tipo inferido, indicando erro em caso contrrio. Note que, nesse caso, o tipo inferido para o parmetro g seria N um a a b, sendo o tipo especicado para o parmetro, na anotao do tipo de f, uma instncia do tipo inferido. Considere agora o seguinte exemplo: f :: ( Char -> Char ^ Bool -> Bool) -> (Char,Bool) f g = (g x, g False) Neste caso, seria indicado erro de tipo na ausncia da anotao de tipo, devido ao fato de que o parmetro g aplicado a argumentos de tipos distintos no corpo de f. Entretanto, a anotao de tipo acima prov uma informao que permite eliminar a restrio do sistema HM que exige parmetros tenham tipo monomrco a anotao de tipo informa explicitamente que g deve poder ser usado no corpo de f tanto com tipo Char -> Char, como com tipo Bool -> Bool. Portanto o inferidor de tipos deve propagar essa informao, de maneira a inferir o tipo do corpo de f em um contexto de tipos em que seja atribuda a g a lista de tipos [Char -> Char, Bool -> Bool]. Para entender como feita propagao dessa informao, precisamos explicar brevemente os tipos de dados usados para representar expresses e tipos na linguagem ncleo. Programas so representados como colees de binding groups, que consistem de associaes entre nomes de smbolos e expresses, podendo ou no incluir uma anotao de tipo. Nosso caso de interesse um binding group que inclua anotaes de tipo. > data Bind a = FunBind a (Maybe (Scheme a)) (Maybe (Alts a)) > | PatBind (Pat a) (Maybe (Scheme a)) (Expr a) > deriving (Eq, Ord, Show, Data, Typeable) > > type Binds a = [Bind a] O tipo de dado algbrico Bind a representa um binding group. O construtor de tipo FunBind usado para associar um nome a um conjunto de alternativas de denies de expresses, cada uma associada a um respectivo padro. Um padro tal como um padro na linguagem Haskell por exemplo, um padro de lista vazia ([]), um padro de tupla (x,y), e assim por diante. Alternativas so representadas

56

Captulo 4. Funes Polimrficas Restritas de Primeira Classe

como pares ([Pat a], Expr a). Um Scheme um tipo polimrico, que pode ou no incluir restries (de classe). Tipos so representados pelo tipo de dados Ty a a seguir: > data Ty a = TVar (TyVar a) > | TCon (TyCon a) > | TyApp (Ty a) (Ty a) > | TyFun (Ty a) (Ty a) > | TyTuple [Ty a] -- Unit type is TyTuple [] > | TyList (Ty a) > | TyAnd [Ty a] -- for Insersection Type annotation. > deriving(Eq, Ord, Show, Data, Typeable) Os construtores de tipos TyApp e TyFun, apesar de sintaticamente semelhantes, tem semnticas diferentes, uma vez que o primeiro representa o tipo da aplicao de um contrutor de tipos a um outro tipo, e o segunrdo representa o tipo de funes. Ao conjunto de construtores de tipo original foi adicionado o construtor TyAnd, para a representao de tipos interseo. A sintaxe de expresses representada pelo tipo de dado Expr a seguir, cujos construtores so autoexplicativos. > data Expr a = Var a > | Con a > | Const (Lit a) > | Lam [Pat a] (Expr a) > | App (Expr a) (Expr a) > | Case (Expr a) (Alts a) > | If (Expr a) (Expr a) (Expr a) > | List [Expr a] > | Tuple [Expr a] > | Let (Binds a) (Expr a) > deriving (Eq, Ord, Show, Data, Typeable) As informaes dadas pela anotao do tipo de uma funo so propagadas para a inferncia do tipo do corpo dessa funo, na forma de um contexto de tipos que contm informao do tipo de cada parmetro. Na nossa implementao, na inferncia dos tipos de denies em um binding group (FunBind), o contexto obtido das anotaes de tipo contidas no binding group passado para a funo tcExpl, que infere o tipo de cada uma das denies alternativas (tcAlts). O trecho de cdigo de tcExpl que corresponde inferncia de tipos para um binding group apresentado a seguir.

4.5. Implementao

57

> tcExpl :: Bind Name -> TcM [Pred Name] > tcExpl (FunBind n (Just sc) (Just alts)) > = do > (ps :=> t) <- freshInst sc > (ps, t) <- tcAlts (skol t) alts > s <- match t t > s <- wf (apply s $ ps :=> t) > ps <- improve ( apply (s @@ s) ps) > pc <- improve ( apply (s @@ s) ps ) > sc <- quantify (apply (s @@ s) (ps :=> t)) > sc <- quantify (pc :=> apply (s @@ s) t) > if sc /= sc then > throwError ("Type Signature error in\n" ++ > (show $ pUnlines [(n :>: sc), (n :>: sc)])) > else return (apply (s @@ s) ps > ............... A funo skol, usada no corpo de tcExpl, simplesmente transforma em constantes de tipo as variveis de tipo que ocorrem em tipos interseo. Isto feito para evitar que estas variveis sejam inadequadamente instanciadas, situao que poderia ocorrer se o tipo inferido para a varivel fosse mais especco que o tipo anotado pelo programador, o que indicado como um erro de anotao de tipo. A funo tcAlts simplesmente chama a funo tcAlt, a qual infere o tipo de cada alternativa individualmente. O cdigo dessas funes apresentado a seguir. Note que o tipo passado para tcAlts repassado para tcAlt. A funo args, denida em tcAlt, associa cada padro ao tipo correspondente na assinatura de tipos provida pelo programador, gerando uma lista de pares (Pat Name,Ty Name), onde name representa um nome de smbolo, e Ty Name um tipo. A funo tcPats usa essa lista de associaes e constri um novo contexto de tipos, as, que por sua vez usado na vericao do tipo da expresso associada ao padro. > tcAlts :: Ty Name -> Alts Name -> TcM ([Pred Name], Ty Name) > tcAlts t alts = do > psts <- mapM (tcAlt t ) alts > let > ps = concatMap fst psts > (t:ts) = map snd psts > mapM_ (unify t) ts

58

Captulo 4. Funes Polimrficas Restritas de Primeira Classe

> > > > tcAlt :: Ty Name -> > tcAlt t (pats, e) = > > > > where > args [] t = [] > args (pat:pats) > args (pat:pats)

s <- getSubst return (apply s ps, apply s t) Alt Name -> TcM ([Pred Name], Ty Name) do (ps, as, ts) <- tcPats (args pats t) (qs, t) <- context as (tcExpr e) return (ps ++ qs, foldr TyFun t ts)

(TyFun arg res) = (pat,arg) : args pats res _ = error " Invalid type annotation."

Durante a inferncia de tipos de expresses, basicamente duas situaes de interesse podem ocorrer: 1) a aplicao de um valor de tipo interseo a um valor cujo tipo no um tipo interseo; 2) a aplicao de uma funo, cujo parmetro tem tipo interseo, a um valor de tipo polimrco. Para tratar essas situaes necessrio modicar, na implementao original, apenas o caso de inferncia de tipos para a aplicao. O exemplo apresentado anteriormente ilustra o caso da situao 1): o parmetro g tem tipo interseo e aplicado a valores de tipos distintos, no corpo da funo f. Nesse caso, o tipo de g deve ser especializado para o tipo do argumento, em cada aplicao. No caso da aplicao g x o tipo de g deve ser especializado para Char -> Char. Essa especializao realizada por meio de matching do tipo T a, onde T o tipo do argumento de g e a uma varivel de tipo fresh, com cada um dos tipos presentes no tipo interseo anotado para g. Dentre esses possveis matching, exatamente um deve ser bem sucedido. Se nenhum matching for bem sucedido, o tipo interseo de g no atende o que requerido pelo argumento da aplicao. Se mais de um matching for bem sucedido, temos uma situao de ambiguidade, em que no seria possvel determinar qual o tipo e, correspondentemente, qual q implementao, de g deveria ser usada nessa aplicao. Esses dois casos so considerados erro de tipo. Considere agora uma aplicao tal como f id, onde f a funo denida acima, e id a funo identidade, cujo tipo inferido como id :: a. a a. Essa aplicao corresponde ao caso 2) mencionado: o tipo do argumento de f, ou seja, o tipo de id, deve poder ser generalizado para o tipo interseo do parmetro de f para que a aplicao seja bem tipada. Mais especicamente, o tipo de id deve ser generalizado para o tipo interseo representado pela lista de tipos [Char -> Char, Bool

4.6. Concluso

59

-> Bool]. Isso feito do seguinte modo: 1 Obtm-se um tipo tal que obtido por fresh isntantiation do tipo do argumento. Nesse caso, teramos = a1 a1 , onde a1 uma varivel fresh. 2 Para cada tipo pertencente ao tipo interseo [Char -> Char, Bool -> Bool], faz-se matching( , ). 3 O tipo para o qual o matching bem sucedido eliminado da lista de tipos (interseo). 4 O processo repetido, a partir do passo 1, at que no reste nenhum tipo na lista (interseo). 5 Para que a aplicao seja bem tipada, todos os matching devem ser bem sucedidos. Por m, para cada aplicao necessrio determinar se corresponde ao caso 1) especializao do tipo da funo, ou ao caso 2) generalizao do tipo do argumento para um tipo interseo. Para isso, em uma aplicao f x, primeiro inferido o tipo de f , para vericar se esse tipo tem parmetro de tipo interseo; se este for o caso, o tipo de x deve ser generalizado; caso contrrio, o tipo de f pode ter que ser especializado (se for um tipo interseo).

4.6

Concluso

Neste captulo foi denido o sistema CTi e apresentado um algoritmo para inferncia de tipos nesse sistema. O sistema CTi constitui uma extenso conservativa do sistema (Hindley-Milner + suporte a sobrecarga por meio de classes de tipos), com a introduo de uma forma restrita de polimorsmo de ordem superior, por meio da possibilidade de especicar o tipo de um parmentro de funo como um tipo interseo. Um prottipo do algoritmo de inferncia de tipos apresentado neste captulo foi implementado na linguagem Haskell, para um subconjunto de expresses dessa linguagem. A forma de polimorsmo de rank superior suportada pelo sistema CTi complementar ao recurso de polimorsmo paramtrico de rank superior. Existem expresses que podem ser tipadas no sistema CTi, tais como as diversas aplicaes da funo foo discutidas anteriormente, mas que no podem ser tipadas em sistemas de polimorsmo de rank superior, se for provida uma nica denio para a funo foo. Em um sistema

60

Captulo 4. Funes Polimrficas Restritas de Primeira Classe

de polimorsmo de rank superior, somente seria possvel tipar essas diversas aplicaes se fossem providas vrias denies para foo, com anotaes de tipo distintas, apropriadas para o uso de foo em cada uma dessas aplicaes, embora em todas a funo foo fosse denida pela mesma expresso. Por outro lado, em um sistema com suporte para polimorsmo paramtrico de rank arbitrrio, seria possvel atribuir tipo a uma expresso tal como map f xs, onde f uma funo polimrca, de tipo, digamos, f :: a, b. ([a] [a]) b, e xs uma lista de elementos polimrcos, de tipo xs :: [a. ([a] [a])]. Essa aplicao possvel em um sistema em que o tipo de map possa ser instanciado impredicativamente. Uma anotao de um tipo de rank superior para uma funo pode tambm ser usada para restringir o comportamento da mesma, garantindo determinadas propriedades, que podem ser derivadas a partir do seu tipo. Isso til para a prova de propriedades de programas, como mostrado em [50].

Captulo 5 Concluso
Neste trabalho apresentamos a denio de um sistema de tipos que constitui uma extenso conservativa do sistema (Hindley Milner + suporte a sobrecarga por meio de classes de tipos), provendo como recurso adicional uma forma restrita de polimorsmo de ordem superior, por meio da possibilidade de especicar o tipo de um parmetro de funo como um tipo interseo. Esse recurso permite denir funes cujo parmetro pode ser usado com diferentes tipos no corpo da denio dessa funo, podendo tal funo ser aplicada tanto a argumentos que so funes de tipo polimrco paramtrico como funes sobrecarregadas. Embora existam diversos trabalhos sobre sistemas de tipos para suporte a sobrecarga, assim como inmeros trabalhos sobre sistemas de tipos interseo, a combinao desses recursos em um mesmo sistema de tipos, tal como apresentada neste trabalho, completamente original. Como discutimos no nal do Captulo 4, a forma de polimorsmo de rank superior suportada pelo sistema CTi, denido neste trabalho, complementar ao recurso de polimorsmo paramtrico de rank superior, existindo expresses que podem ser tipadas em um sistema, mas no no outro, e vice versa. O algoritmo para inferncia de tipos para expresses do sistema CTi descrito neste trabalho foi implementado em Haskell, para um subconjunto de expresses dessa linguagem, naturalmente estendido com a possibilidade de serem especicadas anotaes de tipos em que tipos interseo ocorrem do lado esquerdo do construtor de tipos funcionais.

61

62

Captulo 5. Concluso

5.1

Trabalhos Futuros

Alguns aspectos desse trabalho devem ser ainda concludos ou merecem ser considerados, sendo planejados como trabalhos futuros: 1. A prova das propriedades de correo e de tipo principal para o algoritmo de inferncia de tipo para o sistema CTi. 2. Uma descrio detalhada da implementao do algoritmo de inferncia de tipos. 3. Uma denio formal da semntica de expresses desse sistema e a prova da propriedade de correo so sistema de tipos em relao a essa semntica. 4. A denio de uma verso desse sistema de tipos na forma de um sistema de tipos bidirecional, com regras de derivao e vericao de tipos, e a denio do algoritmo de inferncia de tipos correspondente, com o objetivo de diminuir o requerimento de anotaes de tipo em linguagens baseadas no sistema CTi, por meio da propagao dessas anotaes de tipo ao longo do processo de inferncia de tipos. 5. A implementao de um prottipo desse novo algoritmo de inferncia de tipos. Uma extenso interessante do sistema de tipos aqui proposto seria a sua utilizao como base para a denio de uma sistema ainda mais exvel, que possibilite a passagem de funes sobrecarregadas g como argumento para uma funo f , de maneira que, no corpo de f , g possa ser aplicada a estruturas de dados com elementos de tipos heterogneos, tais como uma lista heterognea. A idia denir o tipo dessa lista heterognea como um tipo [T ], em que t representa todos os possveis tipos de elementos dessa lista; uma lista com tal tipo poderia ser usada seguramente (sem possibilidade de erros de tipo) como argumento de uma funo sobrecarregada g, se, para cada um dos tipos representados por T , existe uma denio de uma instncia em que o parmetro de g tem esse tipo.

Referncias Bibliogrcas
[1] Henk Barendregt. Lambda Calculus: ist Syntax and Semantics. North Holland, 1984. [2] Henk Barendregt, S. Abramsky, D. M. Gabbay, T. S. E. Maibaum, and H. P. Barendregt. Lambda calculi with types. In Handbook of Logic in Computer Science, pages 117309. Oxford University Press, 1992. [3] Carlos Camaro and Luclia Figueiredo. Type inference for overloading, 1999. [4] Carlos Camaro, Rodrigo Ribeiro, Luclia Figueiredo, and Cristiano Vasconcellos. A solution to haskells multi-paramemeter type class dilemma. In Proceedings of 13th Brazilian Symposium on Programming Languages, pages 1921, 2009. [5] Carlos Camaro, Cristiano Vasconcellos, Lucilia Figueiredo, and Joo Nicola. Open and closed worlds for overloading: a denition and support for coexistence. Journal of Universal Computing, 13(6):874890, 2007. [6] Manuel Chakravarty, Gabrielle Keller, and Simon Peyton Jones. Associated type synonyms. In ICFP05: ACM International Conference on Functional Programming, 2005. [7] D. Clement, J. Despeyroux, T. Despeyroux, and G. Kahn. A simple applicative language: Mini-ml. In ACM Symposium on Lisp and Functional Programming, pages 13-27. ACM Press, 1986. [8] M. Coppo and M. Dezani-Ciancaglini. An extension of the basic functionality theory for the -calculus. Notre Dame J. Formal Logic, 21(4):685693, 1980. [9] M Coppo, M Dezani-Ciancaglini, and B. Veneri. Principal type schemes and lambda-calculus semantics. Academic Press, 1980. 63

64

REFERNCIAS BIBLIOGRFICAS

[10] L. Damas and R. Milner. Principal type-schemes for functional programs. In POPL 82: Symposium on Principles of Programming Languages, pages 207212. ACM, 1982. [11] Atze Dijkstra. Stepping through Haskell. PhD thesis, Utrecht University, 2005. [12] Gregory J. Duck, Simon Peyton-Jones, Peter J. Stuckey, and Martin Sulzmann. Sound and decidable type inference for functional dependencies, 2004. [13] Dominic Duggan and John Ophel. Type-checking multi-parameter type classes. Journal of Functional Programming, 12(2):133158, 2002. [14] Jean-Yves Girard. Interprtation fonctionnelle et limination des coupures de larithmtique dordre suprieur. thse detat. In J. E. Fenstad., editor, Proceedings of the Second Scandinavian Logic Symposium, 1972. [15] Cordelia Hall, Kevin Hammond, Simon Peyton-Jones, and Philip Wadler. Type classes in haskell. ACM Transactions on Programming Languages and Systems (TOPLAS), 18(2):109138, 1996. [16] R. Hindley. The principal type-scheme of an object in combinatory logic. Transactions of the American Mathematical Society, 146, 1969. [17] P. Hudak, R. J. M. Hughes, S. Peyton-Jones, and P. Wadler. A history of haskell: being lazy with class. In History of Programming Languages, pages 1211255. ACM Press, 2007. [18] Paul Taylor Jean-Yves Girard, Yves Lafont. Proofs and Types. Cambridge Tracts in Theoretical Computer Science, 1989. [19] Mark P. Jones. A theory of qualied types. In Bernd K. Bruckner, editor, ESOP 92, 4th European Symposium on Programming, volume 582, pages 287 306. Springer-Verlag, 1992. [20] Mark P. Jones. Coherence for qualied types. Technical Report YALEU/DCS/RR989, Yale University, Department of Computer Science, September 1993. [21] Mark P. Jones. Qualied Types: theory and practice. PhD thesis, University of Nottingham, Department of Computer Science, 1994. [22] Mark P. Jones. A system of constructor classes: overloading and implicit higherorder polymorphism. Journal of Functional Programming, 5:135, 1995.

REFERNCIAS BIBLIOGRFICAS

65

[23] Mark P. Jones. Typing haskell in haskell. In ACM Haskell Workshop. ACM Press, 1999. [24] Mark P. Jones. Type classes with functional dependencies. In ESOP00: European Symposium on Programming, volume 1782. LNCS, Springer-Verlag, 2000. [25] Simon Peyton Jones, Mark P. Jones, and Erik Meijer. Type classes: an exploration of the design space. In Haskell Workshop, 1997. [26] A. J. Kfoury and J. Tiuryn. Type reconstruction in nite fragments of second order lambda calculus. Information and Computation, 98(2):228257, 1992. [27] A. J. Kfoury and J. B. Wells. Principality and decidable type inference for niterank intersection types. In POPL99: ACM Conference on Principles of Programming Languages, pages 161174. ACM Press, 1999. [28] Didier Le Botlan and Didier Remy. Mlf: Raising ml to the power of system f. In ICFP2003: International Conference on Functional Programming, pages 2738, 2003. [29] Didier Le Botlan and Didier Remy. Recasting mlf. Information and Computaion, 207(6):726785, 2009. [30] Daan Leijen. Flexible types: robust type inference for rst-class polymorphism. In POPL 09: Proceedings of the 36th annual ACM SIGPLAN-SIGACT symposium on Principles of programming languages, pages 6677. ACM Press, 2009. [31] Dann Leijen. Hmf: Simple type inference for rst-class polymorphism. In ICFP2008: International Conference on Fucntional Programming, pages 283 294. ACM Press, 2008. [32] Dann Leijen. Flexible types: robust type inference for rst-class polymorphism. In POPL2009: International Conference on Principles of Programming Languages, pages 6677. ACM Press, 2009. [33] Dann Leijen and Andres Lh. Qualied types for mlf. In ICFP2005: International Conference on Fucntional Programming, pages 144155, 2005. [34] R. Milner, M. Tofte, R. Harper, and D. MacQueen. The Denition of Standard ML, revised edition. MIT Press, 1997. [35] John Mitchell. Foundations for Porgramming Languages. MIT Press, 1996.

66

REFERNCIAS BIBLIOGRFICAS

[36] John C. Mitchell. Polymorphic type inference and containment. Information and Computation, 76:211249, 1998. [37] M. Odersky and K. Lufer. Putting type annotations to work. In ACM Symposium on Principles of Programming Languages, pages 5467. ACM Press, 1996. [38] S. Peyton-Jones, D. Vytiniotis, S. Weirich, and M. Shields. Practical type inference for arbitrary-rank types. Journal of Functional Programming, 17(1):182, 2007. [39] Simon Peyton-Jones. Haskell 98 language and libraries: the revised report. Cambridge University Press, 4 edition, 2003. [40] Benjamin C. Pierce. Types and programming languages. The MIT Press, 1 edition, 2002. [41] Benjamin C. Pierce and David N. Turner. Local type inference. ACM Trans. Program. Lang. Syst., 22(1):144, 2000. [42] John C. Reynolds. Towards a theory of type structure. In Programming Symposium, Proceedings Colloque sur la Programmation, pages 408423, London, UK, 1974. Springer-Verlag. [43] John C. Reynolds. Towards a theory of type structure. In Programming Symposium, Proceedings Colloque sur la Programmation, pages 408423. Springer-Verlag, 1974. [44] J.A. Robinson. Computational logic: The unication computation. In Machine Intelligence, 6:6372, 1971. [45] C. Shan. Sexy types in action. ACM SIGPLAN Notices, 39(5):15-22, 2004. [46] C. Strachey. Fundamental concepts in programming languages. Journal HigherOrder and Symbolic Computation, 13:1149, April 2000. [47] P. J. Stuckey and M. Sulzmann. A theory of overloading. ACM Transactions on Programming Languages and Systems (TOPLAS), 6(27):154, 2005. [48] M. Sulzmann, T. Schrijvers, and P. J. Stuckey. Principal type inference for ghcstyle multi-parameter type classes. In APLAS06, volume 4279, pages 2643. LNCS, Springer-verlag, 2006. [49] Martin Sulzmann, Gregory J. Duck, Simon P. Jones, and Peter J. Stuckey. Understanding functional dependencies via constraint handling rules. Journal of Functional Programming, 17(1):83129, 2007.

REFERNCIAS BIBLIOGRFICAS

67

[50] Janis Voitlander. Types for Programming Reasoning. PhD thesis, Technische Universitt Dresden, 2009. [51] Dimitrios Vytiniotis, Stephanie Weirich, and Simon Peyton Jones. Boxy types: Inference for higherrank types and impredicativity. In ICFP 06: Proceeding of the 11th ACM SIGPLAN International Conference on Functional Programming, pages 251262. ACM Press, 2006. [52] Dimitrios Vytiniotis, Stephanie Weirich, and Simon Peyton Jones. Fph: rst-class polymorphism for haskell. In ICFP 08: Proceeding of the 13th ACM SIGPLAN International Conference on Functional programming, pages 295306. ACM Press, 2008. [53] P. Wadler and S. Blott. How to make ad-hoc polymorphism less ad hoc. In POPL89: Symposium on Principles of Programming Languages, pages 6076. ACM Press, 1989. [54] David A. Watt. Programming language concepts and paradigms. Prentice-Hall, Inc., Upper Saddle River, NJ, USA, 1990. [55] J. B. Wells. Typability and type checking in the second-order lambda-calculus are equivalent and undecidable. Annals of Pure and Applied Logic, 98(13):111156, 1999.

Você também pode gostar