• Nenhum resultado encontrado

Tipos Alg´ebricos Indexados por Tipos

No documento Programação genérica usando o sistema CT (páginas 84-87)

4.3 Generic Haskell

4.3.5 Tipos Alg´ebricos Indexados por Tipos

Fun¸c˜oes indexadas por tipos s˜ao fun¸c˜oes que possuem um tipo como parˆametro e podem acessar a estrutura de seu argumento de tipo em sua defini¸c˜ao, podendo, assim, assumir comportamentos diferenciados para diferentes tipos[L¨oh04].

Este mecanismo pode ser utilizado n˜ao apenas em defini¸c˜oes de fun¸c˜oes, mas tamb´em em defini¸c˜oes de tipos alg´ebricos. Um Tipo Alg´ebrico Indexado por Tipos (Type-indexed

data type) ´e um tipo alg´ebrico com um argumento de tipo, que ´e utilizado para definir

a estrutura deste novo tipo, ou seja, tipos alg´ebricos indexados por tipos podem ter diferentes implementa¸c˜oes para diferentes argumentos.

Um exemplo de tipo alg´ebrico indexado por tipos s˜ao as chamadas Tries, que s˜ao freq¨uentemente utilizadas como ´ındices para textos. Uma ´arvore de busca digital, ou trie, ´e uma ´arvore de busca que utiliza a estrutura das chaves para organizar a

4.3. Generic Haskell 65

informa¸c˜ao eficientemente[RH02]. Isto quer dizer que ´e necess´ario implementar uma nova trie para cada tipo de chave utilizada. Por exemplo, considere a seguinte imple- menta¸c˜ao de uma trie que utiliza chaves do tipo String:

type FMapChar v = [(Char, v)]

data FMapString v = Trie_String (Maybe v)

(FMapChar (FMapString v))

Neste exemplo o prefixo FMap, presente nos contrutores, ´e uma abrevia¸c˜ao para ma- peamento finito. O primeiro componente do construtor Trie String cont´em o valor associado a uma String vazia e seu tipo ´e Maybe v, ao inv´es de v, devido ao fato de que h´a a possibilidade de uma String n˜ao fazer parte do dom´ınio das chaves desta

trie. Neste caso, o valor deste componente ´e igual a Nothing. O segundo componente

do construtor Trie String realiza o mapeamento de uma trie de chaves do tipo String utilizando uma trie cujas chaves s˜ao caracteres. A partir destas defini¸c˜oes, ´e poss´ıvel definir fun¸c˜oes para a busca de strings:

lookupChar :: ∀v.Char→FMapChar v→Maybe v lookupChar c [ ] = Nothing

lookupChar c ((c’, v):xs)

| c < c’ = Nothing | c == c’ = Just v

| c > c’ = lookupChar c xs lookupString :: ∀v.String→FMapString v→Maybe v lookupString [ ] (Trie_String tn tc) = tn

lookupString (x:xs)(Trie_String tn tc) =

(lookupChar x ⋄ lookupString xs) tc

A defini¸c˜ao de lookupChar ´e direta. Esta fun¸c˜ao percorre seq¨uencialmente a lista de associa¸c˜oes FMapChar e retorna o valor Nothing, caso a chave fornecida n˜ao esteja presente neste mapeamento. A fun¸c˜ao lookupString realiza a busca de uma deter- minada string em uma estrutura FMapString. A primeira equa¸c˜ao da defini¸c˜ao de lookupStringtrata a possibilidade de buscar uma string vazia em uma trie. A ´ultima equa¸c˜ao desta defini¸c˜ao, realiza a busca de uma string n˜ao vazia (x:xs) em dois passos: 1. Primeiramente, busca-se o caractere x na estrutura FMapChar, presente no se- gundo componente do construtor Trie String, obtendo como resultado um valor de tipo Maybe Trie String.

2. Caso o resultado do primeiro passo seja diferente de Nothing, ´e feita a chamada recursiva a lookupString, passando como argumentos o restante da chave (xs) e a sub-´arvore tc.

Para obter este seq¨uenciamento, e prover um tratamento adequado para o valor Nothing, ´e utilizada a composi¸c˜ao mon´adica para o tipo Maybe, representada por ⋄:

(⋄) :: ∀ a b c. (a → Maybe b) → (b → Maybe c) → a → Maybe c (f ⋄ g) = case f a of

Nothing→ Nothing Just b → g b

Antes de apresentar a defini¸c˜ao de uma trie utilizando a sintaxe de Generic Haskell para tipos alg´ebricos indexados por tipos, considere o seguinte exemplo, de uma trie cujas chaves s˜ao ´arvores bin´arias em que caracteres s˜ao armazenados nas folhas. Esta ´arvore ´e representada pelo seguinte tipo alg´ebrico:

data Bush = Leaf Char | Fork Bush Bush

E a trie que utiliza como chaves valores do tipo Bush e sua correspondente fun¸c˜ao de busca ´e mostrada a seguir:

data FMapBush v = Trie_Bush (FMapChar v) (FMapBush (FMapBush v)) lookupBush ::∀ v .Bush → FMapBush v → Maybe v

lookupBush (Leaf c) (Trie_Bush tl tf) = lookupChar c tl lookupBush (Fork bl br) (Trie_Bush tl tf) =

(lookupBush bl ⋄ lookupBush br) tf

Novamente, temos dois componentes, um representando valores constru´ıdos por Leaf, e um componente para valores constru´ıdos utilizando Fork. ´E f´acil perceber que n˜ao apenas as fun¸c˜oes de busca, mas tamb´em os tipos alg´ebricos para tries s˜ao instˆancias de um mesmo padr˜ao gen´erico[RH02].

Para perceber os padr˜oes gen´ericos envolvidos nas defini¸c˜oes dos tipos alg´ebricos e de fun¸c˜oes de busca, considere as seguintes representa¸c˜oes estruturais dos tipos String e Bush e de suas respectivas tries:

type StringRep = Sum (Con Unit) (Con (Prod Char [Char]))

type FMapStringRep v = Prod (Con Maybe) (Prod FMapChar FMapString) type BushRep v = Sum (Con Char) (Con (Prod Bush Bush))

4.3. Generic Haskell 67 ´

E evidente que existem isomorfismos entre a representa¸c˜ao estrutural de um tipo e a representa¸c˜ao estrutural de sua respectiva trie. Estes isomorfismos s˜ao conhecidos como as leis exponenciais (laws of the exponentials)[RH02]:

1 →f in v ∼= v

(t1+ t2) →f in v ∼= (t1 →f in v) × (t2 →f in v)

(t1× t2) →f in v ∼= t1 →f in (t2 →f in v)

Nestas defini¸c˜oes, t →f in v representa o tipo de mapeamentos finitos de t para v.

Por meio destes isomorfismos, ´e poss´ıvel definir um tipo alg´ebrico indexado por tipos FMaphti v, onde cada um dos isomorfismos ´e utilizado em uma equa¸c˜ao que define a estrutura do tipo alg´ebrico, indexado por tipos, em termos do seu parˆametro de tipo. A defini¸c˜ao de FMaphti v ´e mostrada a seguir:

type FMapht::⋆i::⋆ → ⋆ type FMaphUnitiv = Maybe v type FMaphChariv = FMapChar v

type FMaphSum t1t2iv = Prod (FMapht1i v) (FMapht2i v)

type FMaphProd t1t2iv = FMapht1i (FMapht2i v)

Observe que a defini¸c˜ao de um tipo alg´ebrico indexado por tipos ´e similar `a de uma fun¸c˜ao indexada por tipos. Cada equa¸c˜ao que define o tipo alg´ebrico fornece os parˆametros necess´arios para a especializa¸c˜ao, deste tipo para cada um dos casos (tipos primitivos, somas, produtos).

Tipos alg´ebricos indexados por tipos representam uma importante extens˜ao pre- sente em Generic Haskell. Contudo, ´e poss´ıvel representar tipos indexados por tipos utilizando classes de tipos e dependˆencias funcionais[RH02, Jon00]. Al´em disso, em [CKJM05] ´e apresentada uma extens˜ao ao sistema de classes de tipos, chamada tipos associados (associated types), que permite a defini¸c˜ao de tipos alg´ebricos indexados por meio de tipos utilizando classes de tipos e instˆancias.

No documento Programação genérica usando o sistema CT (páginas 84-87)

Documentos relacionados