Вы находитесь на странице: 1из 90

Principios de Lenguajes de Programaci on

A Quick Overview of ML
Emir Mu noz Jim enez
Escuela de Ingenier a en Computaci on Facultad de Ciencias F sicas y Matem aticas emir.munoz@gmail.com Primavera 2011

A Quick Overview of ML

1/90

Agenda I
1 A Quick Overview of ML Interactuando con ML Expresiones Declaraciones Comentarios Funciones Abreviaciones de Tipo Operadores Listas Strings Registros Polimorsmo Expresiones-fn Condicionales Recursi on Tipos de Igualdad
A Quick Overview of ML 2/90

Agenda II
Pattern Matching El Constructor case Exceptions (Excepciones) Declaraciones Datatype Tipos Abstractos Constructores de Tipo Referencias y Asignaci on Iteraci on

A Quick Overview of ML

3/90

A Quick Overview of ML
ML o Meta Language, permite la programaci on funcional, y el dise no de otros lenguajes de programaci on. Existen dos descendientes del ML original: Standard ML y Caml. A pesar que hay varias implementaciones de Standard ML, ellas soportan el mismo core language, y dieren en extensiones, mensajes de error, etc. El sistema de AT&T de dominio p ublico Standard ML of New Jersey (SML/NJ) y el sistema comercial PolyML, son usados para aplicaciones en investigaci on. Tambi en existe una implementaci on para educaci on llamada Edingburgh ML de la University of Edingburgh (con mejoras de Arthur Norman de Cambridge). Esta tiene diferentes salidas a SML/NJ.
A Quick Overview of ML 4/90

Interactuando con ML

ML es un lenguaje interactivo. Com unmente se ejecuta en ventanas shell. A continuaci on, revisaremos simples usos de varias construcciones ML, ilustradas. Las cuales pueden ser copiadas y pegadas en una ventana shell.

A Quick Overview of ML

5/90

Expresiones

El prompt de nivel superior en ML es -. Como ML lee una frase, muestra = hasta que se encuentre una expresi on completa o una declaraci on. El prompt inicial - o el prompt intermedio = normalmente ser an mostrados aqu , aunque hay implementaciones particulares que no los tienen. SML/NJ es llamado sml. El siguiente ejemplo, es la evaluaci on de 2+3
Standard ML of New Jersey v110.69 [built: Mon Jun 8 14:15:08 2009] - 2+3; val it = 5 : int

A Quick Overview of ML

6/90

Expresiones

Continuaci on 1

Luego que SML/NJ comienza imprime un mensaje seguido por val it = () : unit (se explicar a luego). Entonces el prompts muestra - para nuevos ingresos del usuario. El usuario ingresa 2+3; seguido de un ;. ML responde con val it = 5 : int, en una nueva l nea, y muestra el prompt nuevamente. Esta salida muestra que 2+3 se eval ua al valor 5 de tipo int.
Standard ML of New Jersey v110.69 [built: Mon Jun 8 14:15:08 2009] - 2+3; val it = 5 : int - it; val it = 5 : int

A Quick Overview of ML

7/90

Expresiones

Continuaci on 2

Si el usuario ingresa it; seguido de enter, el sistema responde con val it = 5 : int nuevamente. En general, para evaluar una expresi on e uno ingresa e seguida por un ; y un enter; el sistema entonces imprime el valor y tipo de e en el formato mostrado. El valor de la u ltima expresi on evaluada en el nivel superior es recordada en el identicador it.
Edingburgh ML for DOS/Win32s/Unix (C) Edingburgh University & A C Norman - 2+3; > 5 : int - it; > 5 : int

A Quick Overview of ML

8/90

Expresiones

Continuaci on 3

Debido a esto, los ejemplos que mostraremos, est an en el formato ilustrado por,
2+3; > val it = 5 : int it; > val it = 5 : int

Los prompts (-) no son mostrados, la salida de sistema es indicada por >, y los valores de las expresiones son mostrados expl citamente acotados a it. A veces parte de las salidas ser an omitidas (e.g., el tipo).

A Quick Overview of ML

9/90

Declaraciones
La declaraci on val x = e eval ua a e y asocia (binds) el resultado a x.
val x=2*3; > val x = 6 : int it=x; > val it = false : bool

Notar que la declaraci on no afecta a it. El ingresar e; en el nivel superior es en realidad tratado como ingresar let it = e;. El sistema ML (tanto SML/NJ y Edingburgh ML) inicialmente asocian it a un valor especial (), el cual es el u nico valor del tipo un elemento unit.

A Quick Overview of ML

10/90

Declaraciones
Continuaci on 1

Para asociar las variables x1 , x2 , . . . , xn simult aneamente a los valores de las expresiones e1 , e2 , . . . , en uno puede realizar lo siguiente:
La declaraci on val x1 = e1 and x2 = e2 ... and xn = en O val (x1 , x2 , . . . , xn )=(e1 , e2 , . . . , en ).

Estas dos declaraciones son equivalentes.


val y=10 and z=x; > val y = 10 : int > val z = 6 : int val (x,y) = (y,x); > val x = 10 : int > val y = 6 : int

A Quick Overview of ML

11/90

Declaraciones
Continuaci on 2

Una declaraci on d puede ser realizada de forma local a la evaluaci on de una expresi on e, mediante la evaluaci on de la expresi on let d in e end.
let val x=2 in x*y end; > val it = 12 : int x; > val it = 10 : int

A Quick Overview of ML

12/90

Comentarios

Los comentarios en ML comienzan con (* y nalizan con *). Ellos se pueden anidar como par entesis, y pueden extenderse sobre varias lineas, y ser insertados en cualquier espacio que sea permitido.
tr(* comentarios no pueden ir en medio de nombres *)ue; > Error: unbound variable or constructor: tr > Error: unbound variable or constructor: ue 1 (* este comentario es ignorado *) < 2; > val it = true : bool (* Dentro de este comentario (* hay otro anidado *) ! *)

A Quick Overview of ML

13/90

Funciones
Para denir una funci on f con el par ametro formal x y el cuerpo e, debemos realizar la declaraci on: fun f x = e. Para aplicar la funci on f a un par ametro actual e, evaluamos la expresi on: f e.
fun f x = 2*x; > val f = fn : int -> int f 4; > val it = 8 : int

Las funciones son imprimidas como fn en SML/NJ y Fn en Edingburgh ML, ya que una funci on como tal no es imprimible. Luego que fn o Fn es imprimida, el tipo de la funci on tambi en se imprime. Las funciones aqu ser an imprimidas como fn.
A Quick Overview of ML 14/90

Funciones

Continuaci on 1

Aplicando una funci on a un argumento de tipo err oneo resulta en un error de typechecking (revisi on de tipo). El mensaje de error particular depende del sistema ML usado. En SML/NJ:
- f true; std in:12.1-12.6 Error: operator and operand dont agree (tycon mismatch) operator domain: int operand: bool in expression: f true

En Edingburgh ML:
- f true; Type clash in: (f true) Looking for a: int I have found a: bool
A Quick Overview of ML 15/90

Funciones

Continuaci on 2

La aplicaci on asocia con m as fuerza que cualquier otra cosa en el lenguaje; as , por ejemplo, f 3 + 4 signica (f 3) + 4 y no f (3+4). Las funciones de varios argumentos pueden ser denidas as :
fun add (x:int) (y:int) = x+y; > val add = fn : int -> int -> int add 3 4; > val it = 7 : int val f = add 3; > val f = fn : int -> int f 4; > val it = 7 : int

A Quick Overview of ML

16/90

Funciones

Continuaci on 3

La aplicaci on es asociativa por la izquierda, as add 3 4 signica (add 3)4. En la expresi on add 3, la funci on add es aplicada a 3; el valor resultante es la funci on de tipo int -> int la cual suma 3 a su argumento. As , add toma un argumento a la vez. Sin el tipado explicito de los par ametros formales, ML no puede decir si el + es la suma de enteros o reales. El s mbolo + es sobre-cargado. Si la informaci on extra de tipo es omitida, ocurre un error.

A Quick Overview of ML

17/90

Funciones

Continuaci on 4

En SML/NJ:
- fun add x y = x+y; std in:5.16 Error: overloaded variable + cannot be resolved

En Edingburgh ML:
- fun add x y = x+y; Type checking error in: (syntactic context unknown) Unresolvable overloaded identifier: + Definition cannot be found for the type: (a * a) -> a

Este tipo de error de typechecking es relativamente raro. Mucho m as comunes son los errores resultantes de aplicar funciones a argumentos de tipo incorrecto.

A Quick Overview of ML

18/90

Funciones

Continuaci on 5

La funci on add podr a alternativamente haber sido denida para tomar un argumento simple de tipo producto int * int:
fun add(x,y):int = x+y; > val add = fn : int * int -> int add(3,4); > val it = 7 : int let val z = (3,4) in add z end; > val it = 7 : int add 3; > std in:2.1-2.5 Error: operator and operand dont agree (tycon mismatch) > operator domain: int * int > operand: int > in expression: > add 3

A Quick Overview of ML

19/90

Funciones

Continuaci on 6

El mensaje de error mostrado aqu es el generado por SML/NJ. Notar que esta vez el resultado de la funci on ha tenido su tipo dado expl citamente. En general, es suciente para explicitar el tipo cualquier sub-expresi on, siempre y cuando ello elimine la ambig uedad de todos los operadores sobre-cargados. As como tomando argumentos estructurados (e.g., (3,4)) las funciones pueden tambi en retornar resultados estructurados.
fun sumdiff(x:int,y:int) = (x+y,x-y); > val sumdiff = fn : int * int -> int * int sumdiff(3,4); > val it = (7,~1) : int * int

A Quick Overview of ML

20/90

Abreviaciones de Tipo
Se les puede dar nombre a los tipos:
type intpair = int * int; > type intpair defined fun addpair((x,y):intpair) = x+y; > val addpair = fn : intpair -> int (3,5); > val it = (3,5) : int * int (3,5):intpair; > val it = (3,5) : intpair addpair(3,5); > val it = 8 : int

El nuevo nombre es simplemente una abreviaci on; intpair y int*int son completamente equivalentes.
A Quick Overview of ML 21/90

Operadores

+ (suma) y * son operadores construidos como injos. Los usuarios pueden denir sus propios operadores injos usando infix (para operadores asociativos por la izquierda) y infixr para asociativos por la derecha.
infix op1; infixr op2; > infix op1 > infixr op2

Esto simplemente le dice al parser que parsee e1 op1 e2 como op1(e1 ,e2 ) y e1 op2 e2 como op2(e1 ,e2 ).

A Quick Overview of ML

22/90

Operadores

Continuaci on 1
fun (x:int) op1 (y:int) = x + y; > val op1 = fn : int * int -> int 1 op1 2; > val it = 3 : int fun (x:int) op2 (y:int) = x + y; > val op2 = fn : int * int -> int 2 op2 3; > val it = 6 : int

Un injo de precedencia n puede ser creado usando infix n es vez de s olo infix (y infixr n en vez de s olo infixr). Si el n es omitido, se asume una precedencia por defecto de 0. Se le puede decir al parser ML que ignore el estatus injo de una ocurrencia de un identicador, precediendo la ocurrencia con op.
A Quick Overview of ML 23/90

Operadores

Continuaci on 2
op1; > Error: nonfix identifier required op op1; > val it = fn : int * int -> int

El estatus injo de un operador puede ser permanentemente eliminado usando la directiva nonfix.
1 + 2; > val it = 3 : int nonfix +; > nonfix + 1 + 2; > Error: operator is not a function > operator: int > in expression: > 1 + : overloaded
A Quick Overview of ML 24/90

Operadores

Continuaci on 3

Eliminando el estatus injo de operadores construidos no es recomendable. Restauremoslo antes de resultados ca oticos: + es asociativo por la izquierda con precedencia 6.
infix 6 +; > infix 6 +

A Quick Overview of ML

25/90

Listas

Si todos los e1 , e2 , . . . , en tienen tipo ty , entonces la expresi on ML [e1 , e2 , . . . , en ] tiene tipo (ty list). Las funciones est andar sobre listas son:
hd (head), tl (tail), null (la cual testea si una lista es vac ai.e., es igual a []), y los operadores injos :: (cons) y, @ (append o concatenation).

Todos los miembros de una lista deben tener el mismo tipo.

A Quick Overview of ML

26/90

Listas

Continuaci on 1
val m = [1,2,(2+1),4]; > val m = [1,2,3,4] : int list (hd m , tl m) > val it = (1,[2,3,4]) : int * int list (null m , null []) > val it = (false,true) : bool * bool 0::m; > val it = [0,1,2,3,4] : int list [1, 2] @ [3, 4, 5, 6]; > val it = [1,2,3,4,5,6] : int list [1,true,2]; > std in:3.1-3.10 Error: operator and operand dont agree (tycon mismatch) > domain: bool * bool list > operand: bool * int list > in expression: > true :: 2 :: nil

A Quick Overview of ML

27/90

Strings
Una secuencia de caracteres cerrada entre comillas (") es un string.
"this is a string"; > val it = "this is a string" : string ""; > val it = "" : string

El string vac o es "". Un string puede ser explotado en una lista de strings de caracteres simples, con la funci on explode. La inversa de esto es implode, que concatena una lista de strings de caracteres simples en un solo string.

A Quick Overview of ML

28/90

Strings

Continuaci on 1

explode; > val it = fn : string -> string list explode "this is a string"; > val it = > ["t","h","i","s"," ","i","s"," ","a"," ","s","t","r","i","n","g"] > : string list implode it; > val it = "this is a string" : string

A Quick Overview of ML

29/90

Registros

Los registros son estructuras de datos con los denominados componentes. Ellos pueden ser contrastados con tuplas cuyos componentes son determinados por posici on. Un registro con campos x1 , x2 , . . . , xn cuyos valores son v1 , v2 , . . . , vn es creado mediante la evaluaci on de la expresi on: {x1 = v1 , x2 = v2 , . . . , xn = vn }.
val JuanData = {userid = "jdda", sex = "male", married = true, children = 2}; > val JuanData = {children=2,married=true,sex=" male",userid="jdda"} > : {children:int, married:bool, sex:string, userid:string}

A Quick Overview of ML

30/90

Registros

Continuaci on 1

El tipo de {x1 = v1 , x2 = v2 , . . . , xn = vn } es {x1 = 1 , x2 = 2 , . . . , xn = n }, donde i es el tipo de vi . El orden en el cual los componentes de un registro son nombrados no importa.
val JuanData = {sex = "male", userid = "jdda", children = 2, married = true}; > val JuanData = {children=2,married=true,sex=" male",userid="jdda"} > : {children:int, married:bool, sex:string, userid:string} JuanData = JuanData; > val it = true : bool

A Quick Overview of ML

31/90

Registros

Continuaci on 2

El componente nombrado x de un registro puede ser extra do usando el operador especial #x.
#children JuanData; > val it = 2 : int

A las funciones que acceden componentes de registro se les necesita decir expl citamente el tipo del registro que ellas est an accediendo, ya que estos pueden ser varios tipos de registros con los mismos nombres de campos.
fun Sex p = #sex p; > Error: unresolved flex record in let pattern type persondata = {userid:string, children:int, married:bool, sex:string}; > type persondata = {children:int, married:bool, sex:string, userid:string} fun Sex(p:persondata) = #sex p; > val Sex = fn : persondata -> string
A Quick Overview of ML 32/90

Registros

Continuaci on 3

Una tupla (v1 , v2 , . . . , vn ) es equivalente al registro {1=v1 ,2=v2 ,. . .,n=vn } (i.e., tuplas en ML son casos especiales de registros).
{1 = "Hello", 2 = true, 3 = 0}; > val it = ("Hello",true,0) : string * bool * int #2 it; > val it = true : bool

A Quick Overview of ML

33/90

Polimorsmo
Las funciones de procesamiento de listas hd, t1, etc., pueden ser usadas sobre todo tipo de listas.
hd [1,2,3]; > val it = 1 : int hd [true,false,true]; > val it = true : bool hd [(1,2),(3,4)]; > val it = (1,2) : int * int

As hd tiene varios tipos: arriba es usada con tipos (int list) -> int, (bool list) -> bool y (int * int) list -> (int * int). De hecho si ty es cualquier tipo hd tiene el tipo (ty list) -> ty .
A Quick Overview of ML 34/90

Polimorsmo
Continuaci on 1

Las funciones, como hd, con muchos tipos son llamadas polim orcas, y ML usa variables de tipo a,b,c, etc., para representar sus tipos.
hd; > val it = fn : a list -> a

La funci on ML map toma una funci on f (con argumentos tipo a y tipo resultado b), y una lista l (de elementos de tipo a), y retorna la lista obtenida de la aplicaci on de f a cada elemento de l (que es una lista de elementos de tipo b).

A Quick Overview of ML

35/90

Polimorsmo
Continuaci on 2

map; > val map = fn : (a -> b) -> a list -> b list fun add1 (x:int) = x+1; > val add1 = fn : int -> int map add1 [1,2,3,4,5]; > val it = [2,3,4,5,6] : int list

map puede ser usada en cualquier instancia de sus tipos: arriba, tanto a como b fueron instanciadas a int; abajo, a es instanciada a (int list) y b a bool.
map null [[1,2], [], [3], []]; > val it = [false,true,false,true] : bool list

A Quick Overview of ML

36/90

Polimorsmo
Continuaci on 3

Notar que la instancia no necesita ser especicada; es determinada por el type checker (revisor de tipo). Un u til operador de construcci on es la funci on composici on
op o; > val it = fn : (a -> b) * (c -> a) -> c -> b fun add1 n and add2 n > val add1 > val add2 = = = = n+1 n+2; fn : int -> int fn : int -> int

(add1 o add2) 5; > val it = 8 : int

A Quick Overview of ML

37/90

Expresiones-fn
La expresi on fn x => e eval ua a una funci on con par ametro formal x y con cuerpo e. As , la declaraci on fun f x = e es equivalente a val f = fn x => e. Similarmente fun f (x, y )z = e es equivalente a val f = fn (x, y ) => fn z => e. En la teor a de funciones, el s mbolo es usado en lugar de fn; expresiones como fn x => e son a veces llamadas expresiones-, porque ellas corresponden a abstracciones de c alculo- x.e.
fn x => x+1; > val it = fn : int -> int it 3; > val it = 4 : int
A Quick Overview of ML 38/90

Expresiones-fn
Continuaci on 1

La funci on de orden superior map aplica una funci on a cada elemento de una lista sucesivamente, y retorna la lista de resultados.
map (fn x => x*x) [1,2,3,4]; > val it = [1,4,9,16] : int list val doubleup = map (fn x => x@x); > val doubleup = fn : a list list -> a list list doubleup [ [1,2], [3,4,5] ]; > val it = [[1,2,1,2],[3,4,5,3,4,5]] : int list list doubleup []; > val it = [] : a list list

A Quick Overview of ML

39/90

Condicionales

ML tiene condicionales con sintaxis if e then e1 else e2 con el signicado esperado. Los valores de verdad true y false, ambos de tipo bool.
if true then 1 else 2; > val it = 1 : int if 2<1 then 1 else 2; > val it = 2 : int

e1 orelse e2 es una abreviaci on de if e1 then true else e2 y e1 andalso e2 es una abreviaci on de if e1 then e2 else false.

A Quick Overview of ML

40/90

Recursi on

Lo siguiente dene la funci on factorial:


fun fact n = if n=0 then 1 else n*fact(n-1); > val fact = fn : int -> int fact 5; > val it = 120 : int

Notar que el compilador autom aticamente detecta el llamado recursivo. En versiones iniciales de ML, la recursi on deb a ser expl citamente indicada.

A Quick Overview of ML

41/90

Recursi on

Continuaci on 1

Considerar:
fun f n : int = n+1; > val f = fn : int -> int fun f n = if n=0 then 1 else n*f(n-1); > val f = fn : int -> int f 3; > val it = 6 : int

Aqu f 3 resulta en la evaluaci on de 3*f(2). En versiones iniciales de ML, la primera f deber a haber sido usada, as que f(2) tendr a que evaluar a 2+1=3, desde aqu la expresi on f 3 tendr a que evaluar a 3*3=9.

A Quick Overview of ML

42/90

Recursi on

Continuaci on 2

Un estilo alternativo de denir funciones en Standard ML que evita la recursi on forzada, usa val y fn.
fun f n : int = n+1; > val f = fn : int -> int val f = fn n => if n=0 then 1 else n*f(n-1); > val f = fn : int -> int f 3; > val it = 9 : int

Aqu , la ocurrencia de f en n*f(n-1) es interpretada como la versi on previa de f.

A Quick Overview of ML

43/90

Recursi on

Continuaci on 3

La keyword rec despu es de val puede ser usada para forzar una interpretaci on recursiva:
fun f n : int = n+1; > val f = fn : int -> int val rec f = fn n => if n=0 then 1 else n*f(n-1); > val f = fn : int -> int f 3; > val it = 6 : int

Con val rec la ocurrencia de f en n*f(n-1) es interpretada recursivamente.

A Quick Overview of ML

44/90

Tipos de Igualdad
Valores concretos simples como los enteros, booleanos y strings son f aciles de testear para igualdad. Valores de datatypes simples, como pares y registros, cuyos componentes tienen tipos concretos, son tambi en f aciles de testear para igualdad.
y , v ) si y s olo si, v1 = v1 Por ejemplo, (v1 , v2 ) es igual a (v1 2 . v2 = v2

Hay as , una gran clase de tipos cuyos valores pueden ser testeados para igualdad. Sin embargo, en general es indecidible testear igualdad de funciones. As , no es posible sobrecargar = para trabajar propiamente sobre todos los tipos.
A Quick Overview of ML 45/90

Tipos de Igualdad
Continuaci on 1

En versiones previas de ML, = fue interpretado sobre funciones mediante el testeo de igualdad en las direcciones de memoria de la estructura de datos que representa las funciones. Si tal test naliza con un valor true, entonces las funciones fueron ciertamente iguales, pero muchas funciones matem aticamente (i.e., extensionalmente) iguales fueron diferentes usando esta interpretaci on de =. En Standard ML, esos tipos cuyos valores pueden ser testeados para igualdad son llamados tipos de igualdad y son tratados especialmente. Se dan variables de tipo especial que son restringidas s olo a un rango sobre tipos de igualdad. Estas tienen la forma , mientras las variables de tipos ordinarios tienen la forma .
A Quick Overview of ML 46/90

Tipos de Igualdad
Continuaci on 2

La funci on de construcci on = tiene tipo a * a -> bool. Comenzando desde esto, el typechecker de ML puede inferir los tipos que contienen las variables tipo de igualdad.
fun Eq x y = (x = y); > val Eq = fn : a -> a -> bool fun EqualHd 11 12 = (hd 11 = hd 12); > val EqualHd = fn : a list -> a list -> bool

Intentando instanciar una variable de tipo igualdad a un tipo funcional, resulta en un error.

A Quick Overview of ML

47/90

Tipos de Igualdad
Continuaci on 3

En SML/NJ:
hd = hd; > Error: operator and operand dont agree (equality type required) > operator domain: Z * Z > operand: (Y list -> Y) * (X list -> X) > in expression: > = (hd,hd) EqualHd [hd] [hd]; > Error: operator and operand dont agree (tycon mismatch) > operator domain: Z * Z > operand: Y list -> Y list -> bool > in expression: > - : overloaded EqualHd

El uso de tipos de igualdad en Standard ML es considerado controversial: algunos piensan que son demasiado sucios para el benecio que entregan. Es posible que futuras versiones de ML los eliminen.
A Quick Overview of ML 48/90

Pattern Matching

Las funciones pueden ser denidas por pattern matching (coincidencia de patrones). Por ejemplo, aqu hay otra denici on de la funci on factorial.
fun fact 0 = 1 | fact n = n * (fact(n-1)); > val fact = fn : int -> int

Aqu est a la funci on Fibonnaci:


fun fib 0 | fib 1 = | fib n = > val fib = 0 1 fib(n-1) + fib(n-2); = fn : int -> int

A Quick Overview of ML

49/90

Pattern Matching
Continuaci on 1

Supongamos que la funci on f es denida por:


fun f p1 = e1 | f p 2 = e2 . . . | f p n = en

Una expresi on f e es evaluada por coincidencia sucesivas del valor de e con los patrones p1 , p2 , . . . , pn (en este orden) hasta encontrar una coincidencia, digamos con pi . Entonces el valor de f e es el valor de ei . Durante la comparaci on de variables en los patrones, se puede acotar a los componentes de los valores de e, y entonces las variables tienen esos valores durante la evaluaci on de ei .
A Quick Overview of ML 50/90

Pattern Matching
Continuaci on 2

Por ejemplo, la evaluaci on de fib 8 causa 8 es coincidencia con 0 luego con 1, ambos fallan, y entonces con n el cual tiene exito, asociando n con 8. El resultado es entonces el valor de fib(8-1) + fib(8-2) el cual (luego de algunos llamados recursivos), eval ua a 21.
fib 8; > val it = 21 : int

Los patrones pueden ser un tanto elaborados y son t picamente compuestos con constructores. (Tal como los vistos antes.)

A Quick Overview of ML

51/90

Pattern Matching
Continuaci on 3

Los patrones en una denici on de funci on no necesitan ser exhaustivos. En SML/NJ:


- fun foo 0 = 0; std in:33.1-33.13 Warning: match nonexhaustive 0 => ... val foo = fn : int -> int

En Edingburgh ML:
- fun foo 0 = 0; ***Warning: Patterns in Match not exhaustive: 0 => 0 > val foo = fn : int -> int

A Quick Overview of ML

52/90

Pattern Matching
Continuaci on 4

Si una funci on es denida con una coincidencia no-exhaustiva, y luego es aplicada a un argumento cuyo valor no coincide con alg un patr on, un tipo especial de run-time error es llamada una excepci on de resultado (exception). En SML/NJ:
- foo 0; val it = 0 : int - foo 1; uncaught Match exception std in:33.1-33.13

En Edingburgh ML:
- foo 1; Exception raised at top level Warning: optimisations enabled some functions may be missing from the trace Exception: Match raised
A Quick Overview of ML 53/90

Pattern Matching
Continuaci on 5

Los mensajes advierten que una coincidencia no-exhaustiva ser a a veces omitida desde la salida mostrada aqu . Las funciones de construcci on en procesamiento de listas, hd y tl pueden ser denidas por:
fun hd(x::l) = x; > Warning: match nonexhaustive > val hd = fn : a list -> a fun tl(x::l) = l; > Warning: match nonexhaustive > val tl = fn : a list -> a list

Estas deniciones dan exactamente el mismo resultado que las funciones de construcci on, excepto que la lista es vac a []. Donde ellas dieren es en las excepciones lanzadas las excepciones ser an descritas luego.
A Quick Overview of ML 54/90

Pattern Matching
Continuaci on 6

Si x es una variable y p un patr on, entonces el patr on x as p es un patr on que coincide las mismas cosas que p, as tiene el efecto adicional, que cuando sucede una coincidencia el valor coincido es acotado a x. Considerar la funci on RemoveDuplicates: (El wildcard coincide con cualquier cosa.)
fun null [] = true | null = false; > val null = fn : a list -> bool

A Quick Overview of ML

55/90

Pattern Matching
Continuaci on 7
fun RemoveDuplicates[] = [] | RemoveDuplicates[x] = [x] | RemoveDuplicates(x1::x2::l) = if x1=x2 then RemoveDuplicates(x2::l) else x1::RemoveDuplicates(x2::l);

> val RemoveDuplicates = fn : a list -> a list RemoveDuplicates[1,1,1,2,3,4,5,5,5,5,5,6,7,8,8,8]; > val it = [1,2,3,4,5,6,7,8] : int list

La repetici on (y las listas adicionales) de x2::l pueden ser evitadas as :


fun RemoveDuplicates[] = [] | RemoveDuplicates(l as [x]) = l | RemoveDuplicates(x1::(l as x2:: )) = if x1=x2 then RemoveDuplicates l else x1::RemoveDuplicates l;

A Quick Overview of ML

56/90

Pattern Matching
Continuaci on 8

Incidentalmente, notar que no se permiten variables duplicadas en los patrones:


fun RemoveDuplicates[] = [] | RemoveDuplicates(l as [x]) = l | RemoveDuplicates(x::(l as x:: )) = RemoveDuplicates l | RemoveDuplicates(x::l) = x::RemoveDuplicates l; > Error: duplicate variable in pattern(s): x

Funciones an onimas (expresiones-fn) pueden ser denidas por pattern matching usando la sintaxis: fn p1 => e1 | ... | pn => en .
fn [] => "none" | [ ] => "one" | [ , ] => "two" | > val it = fn : a list -> string => "many";

(it [], it[true], it[1,2], it[1,2,3]); > val it = ("none","one","two","many") : string * string * string * string
A Quick Overview of ML 57/90

Pattern Matching
Continuaci on 9

Patrones pueden ser construidos a partir de registros, con ... como un wildcard.
fun IsMale({sex="male",...}:persondata) = true | IsMale = false; > var IsMale = fn : persondata -> bool IsMale JuanData; > val it = true : bool

Una denici on alternativa es:


fun IsMale({sex=x,...}:persondata) = (x = "male");

Una forma permitida mucho m as compacta es:


fun IsMale({sex,...}:persondata) = (x = "male");

El nombre del campo sex es tomado como variable. Pensar en un patr on { ,v, } como la abreviaci on de { ,v=v, }
A Quick Overview of ML 58/90

El Constructor case

El constructor case nos permite computar por casos sobre una expresi on de un datatype. La expresi on case e of p1 => e1 | ... | pn => en , es una forma equivalente para la aplicaci on (fn p1 => e1 | ... | pn => en ) e.

A Quick Overview of ML

59/90

Exceptions (Excepciones)
Algunas funciones est andar crean excepciones en tiempo de ejecuci on bajo ciertos argumentos. Cuando esto sucede, un tipo especial de valor (llamado un paquete de excepci on) es propagado, el cual identica la causa de la excepci on. Este paquete tiene nombres los cuales usualmente reejan la funci on que creo la excepci on; ellos tambi en pueden contener valores.
hd(t1[2]); > uncaught exception Hd i div 0; > uncaught exception Div (i div 0)+1000; > uncaught exception Div

A Quick Overview of ML

60/90

Exceptions (Excepciones)
Continuaci on 1

Las excepciones deben ser declaradas usando las palabras claves exception; ellas deben tener el tipo exn. Las excepciones pueden ser expl citamente creadas mediante la evaluaci on de una expresi on de la forma raise e, donde e es evaluada a un valor de excepci on. Las excepciones son imprimidas ligeramente diferentes en SML/NJ y Edinburgh ML.

A Quick Overview of ML

61/90

Exceptions (Excepciones)
Continuaci on 2

En SML/NJ:
- exception Ex1;exception Ex2; > exception Ex1 > exception Ex2 - [Ex1,Ex2]; > val it = [Ex1(-),Ex2(-)] : exn list - raise hd it; > uncaught exception Ex1

A Quick Overview of ML

62/90

Exceptions (Excepciones)
Continuaci on 3

En Edingburgh ML:
exception Ex1;exception Ex2; > type exn con Ex1 = - : exn > type exn con Ex2 = - : exn - [Ex1,Ex2]; > [-,-] : exn list - raise hd it; Exception raised at top level Warning: optimisation enabled some functions may be missing from the trace Exception: Ex1 raised

A Quick Overview of ML

63/90

Exceptions (Excepciones)
Continuaci on 4

Un constructor de paquete de excepci on llamado name y el cual construye paquetes que contienen valres de tipo ty , es declarado por exception name of ty .
exception Ex3 of string; > exception Ex3 Ex3; > val it = fn : string -> exn raise Ex3 "foo"; > uncaught exception Ex3

A Quick Overview of ML

64/90

Exceptions (Excepciones)
Continuaci on 5

El tipo exn es un datatype cuyo constructores son las excepciones. Es el u nico datatype que puede ser din amicamente extendido. Todos los otros datatypes deben tener todos sus constructores declarados al momento que el datatype es declarado. Debido a que exn es un datatype, las excepciones pueden ser usadas en patrones como otros constructores. Esto es u til para el manejo de excepciones.

A Quick Overview of ML

65/90

Exceptions (Excepciones)
Continuaci on 6

Una excepci on puede ser atrapada (y sus contenidos extra dos) usando una manejador de excepciones (exception handler). Un caso importante especial es la atrapada incondicional de todas las excepciones. El valor de la expresi on e1 handle => e2 es el de e1 , a menos que e1 cree una excepci on, en el cual es el valor de e2 .
hd[1,2,3] handle => 0; > val it = 1 : int hd[] handle => 0; > val it = 0 : int i div 0 handle => 1000; > val it = 1000 : int

A Quick Overview of ML

66/90

Exceptions (Excepciones)
Continuaci on 7

La funci on half, que deniremos, s olo tiene exito (i.e., no se crea excepciones) sobre n umeros pares no-ceros; sobre 0 crea Zero, y con n umeros impares crea Odd.
exception Zero; exception Odd; > exception Zero > exception Odd fun half n = if n=0 then raise Zero else let val m = n div 2 in if n=2*m then m else raise Odd end; > val half = fn : int -> int

A Quick Overview of ML

67/90

Exceptions (Excepciones)
Continuaci on 8

Algunos ejemplos del uso de half:


half 4; > val it = 2 : int half 0; > uncaught exception Zero half 3; > uncaught exception Odd half 3 handle => 1000; > val it = 1000 : int

A Quick Overview of ML

68/90

Exceptions (Excepciones)
Continuaci on 9

Las fallas pueden ser atrapadas selectivamente mediante coincidencia de paquete de excepciones; esto es realizado, on. reemplazando el wildcard por un patr Por ejemplo, si e crea Ex , entonces el valor de e handle Ex1 => e1 | . . . | Exn => en es el valor de ei si Ex es igual a Exi , en otro caso la expresi on-handle crea Ex .
half(0) handle Zero => 1000; > val it = 1000 : int half(1) handle Zero => 1000; > uncaught exception Odd half(0) handle Zero => 1000 | Odd => 1001; > val it = 1000 : int half(3) handle Zero => 1000 | Odd => 1001; > val it = 1001 : int
A Quick Overview of ML 69/90

Exceptions (Excepciones)
Continuaci on 10

En lugar de tener las dos excepciones Zero y Odd, uno podr a tener un solo tipo de excepci on que contiene un string.
exception Half of string; > exception Half fun half n = if n=0 then Half "Zero" else let val m = n div 2 in if n=2*m then m else raise Half "Odd" end; > val half = fn : int -> int

A Quick Overview of ML

70/90

Exceptions (Excepciones)
Continuaci on 11

Una desventaja de este m etodo, es que el tipo de excepci on no es imprimido cuando las excepciones no son detectadas.
half 0; > uncaught exception Half half 3; > uncaught exception Half half(0) handle Half "Zero" => 1000 | Half "Odd" => 1001; > val it = 1000 : int half(3) handle Half "Zero" => 1000 | Half "Odd" => 1001; > val it = 1001 : int

A Quick Overview of ML

71/90

Exceptions (Excepciones)
Continuaci on 12

Alternativamente, uno puede hacer coincidir el contenido del paquete de excepci on a una variable, s, y luego ramicar el valor de coincidencia a s.
half(0) handle Half s => (if s="Zero" then 1000 else 1001); > val it = 1000 : int half(3) handle Half s => (if s="Zero" then 1000 else 1001); > val it = 1001 : int

A Quick Overview of ML

72/90

Declaraciones Datatype
Nuevos tipos (m as que meras abreviaciones) pueden tambi en ser denidos. Datatypes son tipos denidos por un conjunto de constructores que pueden ser usados para crear objetos de ese tipo, y tambi en (en patrones) para descomponer objetos de ese tipo. Por ejemplo, para denir un tipo card, podemos usar el constructor datatype:
datatype card = king | queen | jack | other of int; > datatype card > con jack : card > con king : card > con other : int -> card > con queen : card

A Quick Overview of ML

73/90

Declaraciones Datatype
Continuaci on 1

Tal declaraci on declara king, queen, jack y other como constructores y les da valores. El valor de un constructor 0-ario tal como king es el valor constante king. El valor de un constructor tal como other es una funci on constructor que, dado un valor entero n, produce other(n).
king; > val it = king : card other(4+5); > val it = other 9 : card

A Quick Overview of ML

74/90

Declaraciones Datatype
Continuaci on 2

Para denir funciones que toman su argumento de un tipo concreto, pueden ser usadas expresiones-fn de la forma fn p1 => e1 | ... | pn => en . Tal como una expresi on denota una funci on que dado un valor v selecciona el primer patr on que coincide con v , digamos pi , asocia las variables de pi a los correspondientes componentes del valor, y luego eval ua la expresi on ei .

A Quick Overview of ML

75/90

Declaraciones Datatype
Continuaci on 3

Por ejemplo, los valores de diferentes cartas (cards ) pueden ser denidas de la siguiente manera:
val value = fn king => 500 | queen => 200 | jack => 100 | (other n) => 5*n; > val value = fn : card -> int

Alternativamente, y quiz as m as lucidamente, esto podr a ser denido usando una declaraci on fun.
fun value king = 500 | value queen = 200 | value jack = 100 | value (other n) = 5*n; > val value = fn : card -> int

A Quick Overview of ML

76/90

Declaraciones Datatype
Continuaci on 4

La noci on de datatype es muy b asica y podr a permitirnos construir tipos elementales de ML a partir de cero.
datatype bool = true | false; > datatype bool > con false : bool > con true : bool

y los enteros positivos por;


datatype int = zero | suc of int; > datatype int > con suc : int -> int > con zero : int

A Quick Overview of ML

77/90

Tipos Abstractos
Nuevos tipos pueden tambi en ser denidos mediante abstracci on. Por ejemplo, un tipo time podr a ser denido as :
exception BadTime; > exception BadTime abstype time = time of int * int with fun maketime(hrs,mins) = if hrs<0 orelse 23<hrs orelse mins<0 orelse 59<mins then raise BadTime else time(hrs,mins) and hours(time(t1,t2)) = t1 and minutes(time(t1,t2)) = t2 end; > type time > val maketime = fn : int * int -> time > val hours = fn : time -> int > val minutes = fn : time -> int

A Quick Overview of ML

78/90

Tipos Abstractos
Continuaci on 1

Esto dene un tipo abstracto time y tres funciones primitivas: maketime, hours y minutes. En general, una declaraci on de tipo abstracto tiene la forma abstype d with b end, donde d es una especicaci on de datatype y b es una asociaci on (binding), i.e., el tipo de expresi on que puede seguir a val. Tal declaraci on introduce un nuevo tipo, ty , como queda especicado por la declaraci on de datatype d. Sin embargo, los constructores declarados en ty por d est an s olo disponibles dentro de b. Las u nicas asociaciones que resultan de ejecutar la declaraci on abstype son aquellas especicadas en b.

A Quick Overview of ML

79/90

Tipos Abstractos
Continuaci on 2

As una declaraci on de tipo abstracto simult aneamente declara un nuevo tipo junto con funciones primitivas para el tipo; la representaci on datatype no es accesible fuera de la parte-with de la declaraci on.
val t = maketime(8,30); > val t = - : time (hours t, minutes t); > val it = (8,30) : int * int

Notar que los valores de un tipo abstracto son imprimidos como -, ya que su representaci on es ocultada al usuario.

A Quick Overview of ML

80/90

Constructores de Tipo

Tanto list como * son ejemplos de constructores de tipo; list tiene un argumento (por lo tanto a list), mientras * tiene dos (por lo tanto a * b). Los constructores de tipo pueden tener varias operaciones predenidas asociadas a ellos. Por ejemplo, list tiene null, hd, tl, ..., etc. Debido a pattern matching, no es necesario tener las operaciones predenidas para *.

A Quick Overview of ML

81/90

Constructores de Tipo
Continuaci on 1

Uno puede denir, por ejemplo, fst y snd por:


fun fst(x,y) = x and snd(x,y) = y; > val fst = fn : a * b -> a > val snd = fn : a * b -> b val p = (8,30); > val p = (8,30) : int * int fst p; > val it = 9 : int snd p; > val it = 30 : int

A Quick Overview of ML

82/90

Constructores de Tipo
Continuaci on 2

Un constructor de tipo set, que representa conjuntos mediante listas sin repeticiones, puede ser denido de la siguiente forma:
abstype a set = set of a list with val emptyset = set[] fun isempty(set s) = null s fun member( , set[]) = false | member(x, set(y::z)) = (x=y) orelse member(x, set z) fun add(x, set[]) = set[x] | add(x, set(y::z)) = if x=y then set(y::z) else let val set l = add(x, set z) in set(y::l) end end; > val emptyset = [] : a list > val isempty = fn : a set -> bool > val member = fn : a * a set -> bool > val add = fn : a * a set -> a set
A Quick Overview of ML 83/90

Constructores de Tipo
Continuaci on 3

Notar que la operaci on add asegura que ninguna repetici on de elementos ocurra en la lista, representando el conjunto. Aqu hay un ejemplo usando estos conjuntos:
val s = add(1,add(2,add(3,emptyset))); > val s = - : int set member(3,s); > val it = true : bool member(5,s); > val it = false : bool

A Quick Overview of ML

84/90

Referencias y Asignaci on
Referencias son cajas que pueden contener valores. Los contenidos de tales cajas pueden ser cambiados usando el operador de asignaci on :=. El tipo ty ref es pose da por referencias que contienen valores de tipo ty . Las referencias son creadas usando el operador ref. Esto toma un valor de tipo ty a un valor de tipo ty ref. La expresi on x := e cambia el contenido de la referencia que es el valor de x por el valor de e. El valor de esta expresi on de asignaciones es el valor de prueba (); esto es el u nico valor del tipo de un elemento unit. Las asignaciones son ejecutadas por un efecto secundario, no por su valor.
A Quick Overview of ML 85/90

Referencias y Asignaci on
Continuaci on 1

Los contenidos de una referencia pueden ser extra dos usando el operador ! (mensaje de error debajo para SML/NJ). Las referencias deber an ser s olo reordenadas en circunstancias excepcionales, como la experiencia muestra que su uso incrementa la probabilidad de errores.
x:=1; > std in:7.1-7.4 Error: operator and operand dont agree (tycon mismatch) > operator domain: Z ref * Z > operand: int * int > in expression: > := (x,1)

A Quick Overview of ML

86/90

Referencias y Asignaci on
Continuaci on 2

val x = ref 1 and y = ref 2; > val x = ref 1 : int ref > val y = ref 2 : int ref x; > val it = ref 1 : int ref x:=6; > val it = () : int x; > val it = ref 6 : int ref !x; > val it = 6 : int

A Quick Overview of ML

87/90

Iteraci on

Aqu hay una denici on iterativa de fact (factorial) usando dos referencias locales: count y result.
fun fact n = let val count = ref n and result = ref 1 in while !count > 0 do (result := !count * !result; count := !count-1); !result end; > val fact = fn : int -> int fact 6; > val it = 720 : int

A Quick Overview of ML

88/90

Iteraci on

Continuaci on 1

El punto y coma denota secuenciaci on. Cuando una expresi on e1 ;...;en es evaluada, cada ei es evaluado en turnos y el valor de la expresi on completa es el valor de en . La evaluaci on de while e do c consiste en evaluar e, y si el resultado es true, c es evaluado por sus efectos secundarios, y luego el proceso completo se repite. Si e eval ua a false, entonces la evaluaci on de while e do c termina con valor ().

A Quick Overview of ML

89/90

Consultas?

GRACIAS POR SU ATENCION

Emir F. Mu noz Jim enez


emir.munoz@gmail.com

A Quick Overview of ML

90/90

Вам также может понравиться