Está en la página 1de 31

Una Introduccin a Generic Haskell

Pablo Nogueira School of Computer Science and IT Universidad de Nottingham, Reino Unido
Charla presentada en la Facultad de Inform atica de Madrid, 17 de Diciembre de 2004 Correcciones del 28 de Noviembre de 2005

Mad 17 Dic p. 1/3

Contenido de la charla

1. 2.

Qu e es la programac on gen erica y qu e t ecnicas hay por ah . Presentar las ideas en que se basa Generic Haskell.

Mad 17 Dic p. 2/3

Repaso de conceptos

Dos formas de abstracci on: De control: bucles, condicionales, funciones, rutinas, sincronizaci on, etc. - Separaci on entre interfaz e implementaci on De datos: tipos de datos abstractos, objetos, etc. - Separaci on entre interfaz e implementaci on Parametrismo: abstraer sobre ciertas entidades que pasan a ser par ametros, p.e., una expresi on se puede abstraer a una funci on considerando ciertas variables como par ametros. Encapsulaci on: ocultaci on de la informaci on de implementaci on.

Mad 17 Dic p. 3/3

Genericidad

Genericidad: Parametrismo + Instanciaci on + Encapsulaci on Las formas de genericidad se clasican seg un: 1. Qu e entidades son par ametros. - Generalmente se parametriza sobre valores y tipos de datos. nico programa trabaja con - Single Program Multiple Data: un u cualquier (o un conjunto) de tipos de datos. - Determinan el rango del Los mecanismos de instanciaci on y especializaci on des-generizaci on C omo se mantiene la encapsulaci on.

2. 3.

Mad 17 Dic p. 4/3

Programacin Genrica

Polimorsmo: un valor tiene muchos tipos. Variedades de polimorsmo: Subtipado (= herencia) Reusar mediante extensi on. Param etrico universal: ML, (im)predicativo, etc. Param etrico acotado: type classes, tipos calicados, etc. Ad-hoc: sobrecarga, poliaridad, multim etodos, etc. En el mundo funcional no se usan del todo debido a la tiran a de la inferencia. C++ Standard Template Library: b asicamente param etrico. Politipismo o polimorsmo estructural: PolyP , Generic Haskell, Scrap your Boilerplate. Tipos dependientes: una expresi on de tipos puede contener un valor, p.e., List a n es el tipo de listas de elementos de tipo a que tienen longitud n.

Mad 17 Dic p. 5/3

Haskell 98

Haskell es un lenguaje funcional Puro los efectos se realizan en m onadas. Perezoso sem antica no-estricta, memoizaci on. Polimorsmo universal y acotado Systema Fw + type classes. Fuertemente tipado = ausencia de errores de ejecuci on. Tipos de datos algebraicos con gesti on autom atica de memoria. En realidad Haskell es un lenguaje que se dene por su implementaci on y su implementaci on est andar es el Glasgow Haskell Compiler.

Mad 17 Dic p. 6/3

Polimorsmo paramtrico en Haskell

data List t = Nil | Cons t (List t) length :: List t Int length Nil = 0 length (Cons x xs) = 1 + length xs

-- tipo polimorfico -- funcion polimorfica

Comparar con C++:


template<typename T> int length(List<T>& l) { if (l.empty()) return 0; else return 1 + length (l.tail()); } -- respeta abstraccion

Mad 17 Dic p. 7/3

Tipos de datos genricos

Tipos de datos parametrizados: funciones a nivel de datos. Hay orden superior: se puede parametrizar sobre datos (payload) y funciones de datos (shape). Las mismas ideas a nivel de tipo: parametrismo universal, acotado, estructural, . . . , mecanismos de instanciaci on y especializaci on.

Mad 17 Dic p. 8/3

Ejemplos de tipos algebraicos en Haskell

data TreeInt data Tree a data BTree a b data GTree f a data BList a -- Instanciaciones TreeInt

= Empty | Leaf Int| Node TreeInt TreeInt = Empty | Leaf a = Empty | Leaf a | Node (Tree a) (Tree a) | Node b (BTree a b) (BTree a b)

= GEmpty| GLeaf a | GNode (f (GTree f a)) = Nil | Cons a (BList (a,a)) -- irregular

data BGTree f a b = GEmpty| GLeaf a | GNode b (f (BGTree f a b))

Tree Int

type TreeChar = Tree Char type ArithExp = BTree Int (Int Int Int) type LGTree type BGTree = GTree List = GTree BList

Mad 17 Dic p. 9/3

Tipos y orden

El tipo de una funci on est a capturado por la siguiente gram atica: ::= |

Donde engloba los tipos base, p.e., Int o Char. El orden de la funci on se calcula como sigue: orden() = 0 orden(1 2 ) = m ax( 1 + orden(1 ), orden(2 ) )

Una funci on f es de orden superior si orden(f ) > 0

Mad 17 Dic p. 10/3

Tipos y gneros

Al nivel de tipos, el g enero (kind) de una funci on de tipos captura el orden y la aridad. El g enero es el g enero de los tipos que no son funciones de tipo. ::= |

orden() orden(1 2 )

= 0 = m ax( 1 + orden(2 ), orden(2 ) )

Una funci on de tipos t es de orden superior si orden(t) > 0. No exactamente el tipo de un tipo: type classes.

Mad 17 Dic p. 11/3

Ejemplos de tipos y sus gneros

Int TreeInt Tree Tree Int BTree BTree Char GTree GTree List BGTree BList

: * : * : * * : * : * * * : * * : (* *) * * : * * : (* *) * * * : * *

BTree Char Int : *

GTree List Int : *

Mad 17 Dic p. 12/3

Politipismo (I)

Las funciones y tipos polim orcos son param etricos sobre tipos de datos. La instanciaci on es una sustituci on, p.e.:
length :: a:*. List a Int

La funci on calcula la longitud de la lista independientemente del ametro impl cito valor de la variable de tipo a, que es un par (Systema F ). Las funciones y tipos polit picos tambi en son param etricos sobre otros tipos, pero la instanciaci on es m as compleja, basada en la estructura de la denici on del tipo de datos:
length t:* * :: a:*. t a Int

Mad 17 Dic p. 13/3

Politipismo (II)

gsize_List gsize_Set

:: List a Int :: Set a Int

gsize_BTree :: BTree a b Int gsize_GTree :: ( b. f b Int) GTree f a Int

nica funci Podemos generalizar a una u on?


gsize :: ? Int

Los tipos de sus instanciaciones nos est an despistando.

Mad 17 Dic p. 14/3

Generalicemos las instancias (I)

length :: List a Int length [] = 0 length (x:xs) = 1 + length xs gsizeL :: a:*. (a Int) (List a Int) gsizeL gsa [] = gUnit [] gsizeL gsa (x:xs) = gsa x + gsizeL gsa xs length = gsizeL (const 1) gUnit = const 0 -- fijado !

Mad 17 Dic p. 15/3

Generalicemos las instancias (II)

sizeT :: BTree a b Int sizeT Empty = 0 sizeT (Leaf x) = 1 sizeT (Node x l r) = 1 + sizeT l + sizeT r

gsizeT :: a:*. (a Int) ( b:*. (b Int) (BTree a b Int)) gsizeT gsa gsb Empty gsizeT gsa gsb (Leaf x) = gUnit Empty = gsa x + gsizeT gsa gsb r sizeT = gsizeT (const 1) (const 1)

gsizeT gsa gsb (Node x l r) = gsb x + gsizeT gsa gsb l

Mad 17 Dic p. 16/3

Generalicemos las instancias (III)

sizeG :: GTree f a Int sizeG GEmpty = 0 sizeG (GLeaf x) = 1 sizeG (GNode y) = ? gsizeG :: f:* *. ( a:*. (a Int) (f a Int)) ( a:*. (a Int) (GTree f a Int)) gsizeG gsf gsa GEmpty = gUnit GEmpty gsizeG gsf gsa (GLeaf x) = gsa x gsizeG gsf gsa (GNode y) = gsf (gsizeG gsf gsa) y

Mad 17 Dic p. 17/3

Generalicemos el tipo (I)

t:* *.gsize :: a:*.(a Int) (t a Int) t:* * *.


gsize :: a:*. (a Int) ( b:*. (b Int) (t a b Int))

t:(* *) * *.
gsize :: t:* *. ( a:*. (a Int) (t a Int)) ( b:*. (b Int) (t t b Int))

Aqu hay un patr on inductivo sobre el g enero de t.

Mad 17 Dic p. 18/3

Generalicemos el tipo (II)

Size es un tipo polig enero (polykinded) denido inductivamente en ametro. funci on del g enero del tipo t que toma como par
type Size * t = t Int t = a. Size k a Size l (t a) type Size k l

La notaci on Size k t indica que Size es param etrico en el g enero k y enero. toma un tipo t de dicho g Por ejemplo:
Size (* *) (* *) = t. Size * * = t. ( a. Size * ( a. Size * GTree t Size * * a Size * a Size * (GTree t) (t a)) ((GTree t) a))

= t. ( a. (a Int) t a Int) ( a. (a Int) GTree t a Int)

Mad 17 Dic p. 19/3

Generalicemos el cuerpo (I)

La estructura de los datos sugiere la estructura de la soluci on, inclusive para tipos irregulares (recursi on no uniforme). Tipos b asicos y Unit tienen un tama no jo. Los par ametros del tipo llevan asociados funciones argumento que se pasan como argumento. La denici on de la funci on se determina a partir de la denici on de la estructura del tipo (sumas de productos).

Mad 17 Dic p. 20/3

Generalicemos el cuerpo (II)

La funci on gsize toma como argumento el tipo t y tiene como tipo Size k t, donde k es el g enero de t.
gsize t:k gsize Char gsize Int gsize Bool gsize Unit gsize a+b gsize a+b gsize ab :: Size k = const 0 = const 0 = const 0 = const 0 gsa gsb (Inl x) = gsa x gsa gsb (Inr y) = gsb y gsa gsb (x,y) = gsa x + gsb y t

Mad 17 Dic p. 21/3

Denicin que hace la recursin explcita

gsize t:k gsize Char gsize Int gsize Bool gsize Unit gsize a+b gsize a+b gsize ab

:: Size k = const 0 = const 0 = const 0 = const 0

(Inl x) = gsize a (Inr y) = gsize b (x,y) = gsize a

x y x + gsize b y

Mad 17 Dic p. 22/3

Instanciaciones y abstraccin genrica

gsize t:* * gsize t:* * *

:: (a Int) (t a Int) :: (a Int) (b Int) (t a b Int)

length t:* * length t sizeT t:* * * sizeT t

:: t a Int = gsize t (const 1)

:: t a b Int = gsize t (const 1) (const 1)

Mad 17 Dic p. 23/3

Ejemplos de uso

aTree = Node A (Leaf 2) (Leaf 3) gsize BTree Int Char > 0 gsize BTree Int > 1 gsize BTree > 1 gsize BTree > 3 gsize List > 11 (const 1) "hello world" (const 1) (const 1) aTree (const 0) (const 1) aTree (const 1) aTree aTree

Mad 17 Dic p. 24/3

Implementacin

Una posible forma de programar la funci on polit pica es utilizar un valor que codique la estructura de sumas y productos del tipo. La instanciaci on de la funci on gen erica se realiza siguiendo la estructura del tipo argumento a partir de un patr on (template) que indica lo que hacer para cada suma, producto, o tipo b asico. As , por ejemplo, una llamada:
gsize List (const 1) [1,2,4]

Es en realidad una llamada a:


gsizeL (const 1) [1,2,4]

Donde la denici on de gsizeL se ha obtenido a partir de un patr on y siguiendo la estructura de sumas de productos de List.

Mad 17 Dic p. 25/3

Funcin map politpica

type Map *

t1 t2

= t1 t2 = a1 a2 t t

type Map k l

t1 t2

a1 a2. Map k
gmap t:k gmap Int gmap Unit gmap ab gmap a+b gmap a+b gmap List > "ABC" gmap BTree

Map l

(t1 a1) (t2 a2)

:: Map k = = (x,y) id id

= (gmap a

x, gmap b x) y)

y)

(Inl x) = Inl (gmap a (Inr y) = Inr (gmap b chr [65, 66, 67]

ord chr (Node A (Leaf 66) (Leaf 67))

> Node 65 (Leaf B) (Leaf C)

Mad 17 Dic p. 26/3

Explicacin del tipo

El siguiente tipo polig enero no es sucientemente expresivo:


type Map * t = t t t = a. Map l a Map k (t a)

type Map l k

Por ejemplo:
Map * * List = a. Map * a Map * (List a)

= a. (a a) (List a List a)

Soluci on: usar dos variables en la denici on del tipo polig enero (Map k t1 t2), y forzar a que el tipo de gsize sea para un mismo tipo:
gsize t:k :: Map k t t

Mad 17 Dic p. 27/3

Resumen

Una funci on polit pica es en realidad una familia de funciones; no s olo polim orcas sino tambi en sobrecargadas (overloaded) como la igualdad. Son catamorsmos: pretty-printers, igualdad, map, crush, codicaci on, tama no, etc. El tipo polig enero de la funci on es un patr on inductivo sobre el g enero del tipo de datos que la funci on toma como argumento. El cuerpo de la funci on es un patr on inductivo sobre la estructura (sumas de productos) de la denici on de dicho tipo argumento. Implementaci on: preprocesado, traducci on a funciones con polimorsmo de rango-n en Haskell.

Mad 17 Dic p. 28/3

Ms cosas

Type-indexed data types: tipos cuya denici on depende de la estructura de otro tipo. Dependency-style Generic Haskell. Extensi on de funciones (especializaci on). Seleccionar la codicaci on interna en forma de sumas de productos mediante vistas. Implementaci on por medio de type classes: Generics for the masses.

Mad 17 Dic p. 29/3

Anlisis: Ventajas

nica que computa sobre cualquier tipo Genericidad: una funci on u de datos denido en una cl ausula data. Podemos jugar con las funciones par ametro para obtener differentes c omputos.

Mad 17 Dic p. 30/3

Anlisis: Desventajas

La funci on es gen erica s olo en un tipo, no varios. No se puede programar un fold gen erico: el tipo de la funci on polit pica se determina a partir del g enero del tipo argumento, que no nos dice nada sobre su estructura.
type Fold * t = a:*. t ?? a

Necesitamos una funci on por cada constructor de valores. No se soportan tipos algebraicos restringidos, p.e.:
data Ord a Set a = MkSet [a]

Hay que saber c omo se realiza la instanciaci on para poder programar el patr on gen erico (p.e., sumas y productos se asocian a derechas). Grave: no se respeta la abstracci on de datos.

Mad 17 Dic p. 31/3

También podría gustarte