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