Corrigé
Transcription
Corrigé
Série d’exercices #2 IFT2035 19 septembre 2007 1 Quicksort chpivot :: [Int] -> Int chpivot (h:_) = h sep :: Int -> [Int] -> ([Int], [Int]) sep piv [] = ([], []) sep piv l = (filter (< piv) l, filter (> piv) l) quicksort :: [Int] -> [Int] quicksort [] = [] quicksort l = let piv = chpivot l (left, right) = sep piv l (ll, lr) = (quicksort left, quicksort right) in ll ++ [piv] ++ lr -- Version expéditive: qsort :: [Int] -> [Int] qsort [] = [] qsort (x:xs) = qsort [y | y <- xs, y < x] ++ [x] ++ qsort [y | y <- xs, y >= x] -- $Id: demo02-sort.hs,v 1.1 2009/09/21 16:54:54 haguenad Exp $ 2 Micro-optimiseur data Exp = Enum Int -- Une constante 1 | Eplus Exp Exp -- e1 + e2 | Etimes Exp Exp -- e1 * e2 deriving Show optimize :: Exp -> Exp optimize (Enum x) = Enum x optimize (Eplus a b) = case (optimize a, optimize b) of (Enum 0, b) -> b (a, Enum 0) -> a (a, b) -> Eplus a b optimize (Etimes a b) = case (optimize a, optimize b) of (a@(Enum 0), _) -> a (a, b@(Enum 0)) -> b (Enum 1, b) -> b (a, Enum 1) -> a (a, b) -> Etimes a b Exemples : Main> optimize (Eplus (Enum Enum 42 Main> optimize (Eplus (Enum Etimes (Enum 42) (Enum 2) Main> optimize (Eplus (Enum Enum 42 Main> optimize (Eplus (Enum Enum 0 3 0) (Enum 42)) 0) (Etimes (Enum 42) (Enum 2))) 0) (Etimes (Enum 42) (Enum 1))) 0) (Etimes (Enum 42) (Enum 0))) Nombres de Church 1. Inférer le type de chacunes des 3 expressions zero, succ et nat2int. (a) zero ≡ λf.λx.x i. Méthode intuitive Le terme à typer zero est une λ-abstraction : on écrit λf.λx.x : τ0 → τ1 2 On doit ensuite typer le corps de cette abstraction, qui est λx.x ; on écrit λx.x : τ2 → τ3 avec le type de retour τ1 de zero égal au type de son corps. On a donc τ1 = τ2 → τ3 . De plus, λx.x retourne une valeur du même type que le terme pris en paramètre, on a donc λx.x : τ2 → τ2 , et τ2 → τ2 = τ2 → τ3 . Le type de zero est τ0 → τ2 → τ2 . En changeant les noms de variable, on peut écrire ce type α → β → β. ii. Méthode plus formelle : on cherche parmi les règles de typage celle qui peut s’appliquer à notre cas, et on remplace ses variables par les sous-termes de notre terme concret. Puis on utilise le même procédé pour typer les termes qui apparaissent dans les prémisses de la règle. Γ1 , x : τ2 ` x : τ3 Lam Γ1 = Γ0 , f : τ0 ` λx.x : τ2 → τ3 Lam Γ0 ` λf.λx.x : τ0 → τ1 Avec pour contraintes : – τ1 = τ2 → τ3 – τ2 = τ3 On résout les contraintes pour obtenir zero : τ0 → τ2 → τ2 , soit zero : α → β → β. (b) succ ≡ λn.λf.λx.f (n f x) – avec la méthode formelle : Γ3 ` n : τ 8 → τ 9 Γ3 ` f : τ 8 Γ3 ` n f : τ 7 → τ 6 Γ3 ` f : τ 6 → τ 5 App Γ3 ` x : τ 7 Γ3 ` n f x : τ 6 Γ3 = Γ2 , x : τ4 ` f (n f x) : τ5 Γ2 = Γ1 , f : τ2 ` λx.f (n f x) : τ4 → τ5 Γ1 = Γ0 , n : τ0 ` λf.λx.f (n f x) : τ2 → τ3 Γ0 ` λn.λf.λx.f (n f x) : τ0 → τ1 Avec pour contraintes : – τ1 = τ2 → τ3 3 App App Lam Lam Lam – τ3 = τ4 → τ5 – τ2 = τ6 → τ5 = τ8 – τ4 = τ7 – τ9 = τ7 → τ6 – τ0 = τ8 → τ9 On résout les contraintes pour obtenir succ : ((τ6 → τ5 ) → τ4 → τ6 ) → (τ6 → τ5 ) → τ4 → τ5 , soit succ : ((α → β) → γ → α) → (α → β) → γ → β. (c) nat2int = λn.n (λx.x + 1) 0– avec la méthode « intuitive » : Le type de + est Int → Int → Int, donc x est de type Int, et λx.x+1 est de type Int → Int. Comme n est appliqué à deux arguments, son type est de la forme τ0 → τ1 → τ2 , avec τ0 égal au type de λx.x + 1 (τ0 = Int → Int) et τ1 égal au type de 0 (τ1 = Int), i.e. n : (Int → Int) → Int → τ2 . Enfin, nat2int est du type de son paramètre (n) vers le type de son corps. Le corps de nat2int est n appliqué à deux termes : il est de type τ2 . On conclut nat2int : ((Int → Int) → Int → τ2 ) → τ2 , qu’on peut écrire ((Int → Int) → Int → α) → α. 2. Évaluation de trois ≡ succ (succ (succ zero))). β → succ (succ ((λf.λx.f (zero f x)))) ≡ succ (succ ((λf.λx.f ((λf.λx.x) f x)))) β → succ (succ ((λf.λx.f ((λx.x) x)))) β → succ (succ ((λf.λx.f x))) ≡ succ ((λn.λf.λx.f (n f x)) λf.λx.f x) β → succ (λf.λx.f ((λf.λx.f x) f x)) β → succ (λf.λx.f ((λx.f x) x)) β → succ (λf.λx.f (f x)) ≡ (λn.λf.λx.f (n f x)) λf.λx.f (f x) β → λf.λx.f ((λf.λx.f (f x)) f x) β → λf.λx.f ((λx.f (f x)) x) β → λf.λx.f (f (f x)) 3. Évaluation de nat2int trois. On note s ≡ λx.x + 1. nat2int trois ≡ (λn.n (λx.x + 1) 0) trois β → trois (λx.x + 1) 0 ≡ (λf.λx.f (f (f x))) s 0 4 β → (λx.s (s (s x))) 0 β → s (s (s 0)) ≡ s (s ((λx.x + 1) 0)) β → s (s (0 + 1)) ≡ s ((λx.x + 1) (0 + 1)) β → s ((0 + 1) + 1) ≡ (λx.x + 1) ((0 + 1) + 1) β → (((0 + 1) + 1) + 1) $Id: demo02.tex,v 1.2 2009/09/21 18:53:44 haguenad Exp $ 5