Programmation 2 : Modules
Etienne Lozes
Comment imiter les modules pour le type int
?
module CType = sig
val inc : unit -> int
end
module C : CType = struct
let c = ref 0
let inc () = c:= 'a+1; !c
end
let createc () =
let x = ref 0 in
fun () -> (
x := !x + 1; !x)
let inc1 = createc ()
let inc2 = createc ()
⟶ inc1
et inc2
ont leur propre compteur
-
Similaire à ce qu’on fait avec des modules
-
MAIS : marche bien pour des int, mais pas pour d’autres types
Multi-ensembles
type 'a multiset = ('a*int) list
Dans le .mli
:
type 'a multiset
val empty : 'a multiset
val add : 'a -> 'a multiset -> 'a multiset
Puis : on compile le .mli
puis le .ml
ocamlc multiset.mli
ocamlc multiset.ml
Foncteurs
module type SET
Ensemble : on le muni d’une fonction d’ordre, pour pouvoir faire une recherche dichotomique
- Programmation fonctionnelle :
-
pour raisonner en termes de fonctionnalités
- Programmation orientée objet :
-
pour raisonner en termes d’objets
Mixin Classes
- Classe abstraite :
-
pas d’implémentation de méthodes, on ne peut pas l’instancier
Multiple dispatch
Surcharge des méthodes en fonction des types des arguments
⟶ implémenté de base dans Perl6 :
class Test {
multi method identity(Int $x){
return "$x is an integer";
}
multi method identity(Str $x){
return qq<"$x" is a string.>;
}
}
my Test $t .= new();
$t.identify(42);
$t.identify("weasel");
Dispatch partiel aussi possible !
class Test {
multi method identity(Int $x ;; Str $text){
...
}
multi method identity(Str $x ;; Str $text){
return qq<"$x" is a string.>;
}
}
⟶ ;; Str $text
pas utilisé pour déterminer dynamiquement quelle subroutine/méthode utiliser.
En OCamL : références pas polymorphes :
let id = ref (function x = x) in
id:=succ;
id "foo";;
⟶ Problème : ⟹ variables monomorphes (notées
'_a
) : instanciées définitivement dès la première utilisation.
Idem : Les références sont des objets qui ont
- un attribut : le contenu
- deux méthodes : lecture et écriture
⟶ donc si on permet d’avoir des objets ou références polymorphes, on ne peut plus assurer la conservation des types lors de la $𝛽$-réduction.
NB : on peut avoir des variables d’instances mutables mais privées
Ex:
Si un objet a la méthode polymorphe :
map : ∀𝛼, (𝛼->𝛽) -> 𝛼 list -> 𝛽 list
l’objet n’est pas lui-même polymorphe.
Attention :
< dépôt : float -> unit; ..> -> float -> < dépôt : float -> unit; ..>
n’est pas le même type que
(< dépôt : float -> unit; ..> as 'a) -> float -> 'a
\[S ⟶ T ≤ U ⟶ V \\ ⟺ \begin{cases} U ≤ S \text{ (contravariant)}\\ T ≤ V \text{ (covariant)}\\ \end{cases}\]
et
\[𝜇X.⟨m : X ⟶ unit; ..⟩ ≤ 𝜇Y.⟨m : Y ⟶ unit; ..⟩\]ssi il y a égalité des types.
Si $X ≤ Y$ :
\[𝜇X.⟨m : X; n: int; ..⟩ ≤ 𝜇Y.⟨m : Y; ..⟩\]DONC :
Si $X ≤ Y$ :
\[𝜇X.⟨m : X ⟶ unit; n: int; ..⟩ ≤ 𝜇Y.⟨m : Y ⟶ unit; ..⟩ ⟺ X ≥ Y ⟺ X = Y\]\[E := [ ] \mid Ea \mid vE\] \[(𝜆x. e)((𝜆y.y)3) \\ E[] = (𝜆x.e)([]) \\ E[(𝜆y.y)3] ⟶ E[3]\]
$(𝜆y.y)3⟶3$ | |
---|---|
$E[(𝜆y.y)3] ⟶ E[3]$ |
Continuations
E[callcc v] → E[v(λx.E[x])]
E[throw k v] → kv
1 + (callcc 𝜆k. k 3) = 1 + (1 + 3)
callcc (𝜆k. 1 + throw k 3) = 3
callcc (𝜆k'. 1 + (callcc 𝜆k. k' 3)) = 3
1 + callcc(𝜆k. 3) = 4
Monades
OCamL :
let bind f (gx,gs) = let fx, fs = f gx in (fx, gs^fs)
let return x = (x, "")
En Haskell :
import Data.Complex
bind :: (Complex Float -> [Complex Float]) -> ([Complex Float] -> [Complex Float])
bind f l = concat (map f l)
return x = [x]
lift f = return . f
g :: c -> a
f :: a -> b
f' :: a -> StdGen -> (b, StdGen)
g' :: c -> StdGen -> (a, StdGen)
g'(x) :: StdGen -> (a, StdGen)
-- On veut pouvoir définir f'.g'
bind :: (a -> StdGen -> (b, StdGen)) -> (StdGen -> (a, StdGen)) -> (StdGen -> (b, StdGen))
bind f x seed = let (a', seed') = x seed in f a' seed'
return a seed = (a, seed)
lift f = return . f
empty = Semaphore(1)
maleSwitch = Lightswitch()
femaleSwitch = Lightswitch()
maleMultiplex = Semaphore(3)
femaleMultiplex = Semaphore(3)
femaleSwitch.lock(empty)
femaleMultiplex.wait()
# bathroom for women
femaleMultiplex.signal()
femaleSwitch.unlock(empty)
maleSwitch.lock(empty)
maleMultiplex.wait()
# bathroom for men
maleMultiplex.signal()
maleSwitch.unlock(empty)
⟹ Starvation possible :
Solution :
turnstile.wait()
femaleSwitch.lock(empty)
turnstile.signal()
femaleMultiplex.wait()
# bathroom for women
femaleMultiplex.signal()
femaleSwitch.unlock (empty)
turnstile.wait()
maleSwitch.lock(empty)
turnstile.signal()
maleMultiplex.wait()
# bathroom for men
maleMultiplex.signal()
maleSwitch.unlock (empty)
Leave a comment