• [^] # Re: go 2.0

    Posté par . En réponse au journal Pourquoi la recherche en langages de programmation ?. Évalué à 2.

    En Ocaml, le code de base ne me pose pas de problème, si tu joues avec les modules et leur définition et un gadt au milieu, je vais beaucoup transpirer.

    Qu'est-ce qui te pose problème avec les modules ? Ce sont juste des enregistrements (tout comme les objets) avec des déclarations de type (pas comme les objets : les modules c'est des objets sous stéroïdes). Exemples :

    (* un point en 2D vu comme un enregistrement *)
    type pt_2D = {x : float; y :float}
    (* un point en 2D vu comme un objet *)
    class type obj_pt_2d = object
     method x : float
     method y : float
    end
    (* un point en 2D vu comme un module *)
    module type mod_pt_2D = sig
     val x : float
     val y : float
    end
    (* une valeur pour chaque type représentant le même point *)
    let rp : pt_2D = {x = 1.0; y = 2.0}
    let op : obj_pt_2d = object method x = 1.0 method y = 2.0 end
    module MP : mod_pt_2D = struct let x = 1.0 let y = 2.0 end
    rp.x = op#x && rp.y = op#y && rp.x = MP.x && rp.y = MP.y;;
    - : bool = true

    Contrairement aux enregistrements, on peut étendre les objets et modules par héritage :

    class type obj_pt_3D = object
     inherit obj_pt_2d
     method z : float
    end
    module type mod_pt_3D = sig
     include mod_pt_2D
     val z : float
    end
    let op_3D : obj_pt_3D = object
     method x = op#x
     method y = op#y
     method z = 3.0 
    end
    module MP_3D = struct include MP let z = 3.0 end
    op_3D#x = MP_3D.x && op_3D#y = MP_3D.y && op_3D#z = MP_3D.z;;
    - : bool = true

    mais seuls les modules peuvent contenir des déclarations de type, ce qui rend le concept plus abstrait, c'est à dire plus générique. ;-)

    module type Point_2D_t = sig
     (* type des coordonnées *)
     type t
     (* coordonnées du point *)
     val x : t
     val y : t
    end
    (* les annotations de type ne sont pas nécessaires, je les
     mets juste pour souligner qu'ils réalisent la signature *)
    module Pt_float : Point_2D_t with type t = float = struct
     type t = float
     include MP
    end
    module Pt_int : Point_2D_t with type t = int = struct
     type t = int
     let x = 1
     let y = 2
    end

    On pourrait faire la même chose en utilisant un enregistrement paramétrique : généricité sur les enregistrements (avec les objets, ça marche aussi).

    type 't pt_2D_t = {x : t; y : t}
    let p_float : float pt_2D_t = { x = 1.0 ; y = 2.0}
    let p_int : int pt_2D_t = {x = 1; y = 2}
    Pt_float.x = p_float.x && Pt_float.y = p_float.y;;
    - : bool = true
    Pt_int.x = p_int.x && Pt_int.y = p_int.y;;
    - : bool = true

    Mais là où seuls les modules peuvent exprimer un tel degré de généricité, c'est lorsque le type déclaré dans le module est lui-même paramétrique.

    module type Par = sig
     type 'a t
     type u
     val v : u t
    end
    module M : Par with type 'a t = 'a list and type u = string = struct
     type 'a t = 'a list
     type u = string
     let v = ["Hello World !"]
    end
    module N : Par with type 'a t = 'a option and type u = int = struct
     type 'a t = 'a option
     type u = int
     let v = Some 1
    end

    Les modules permettent de pousser la généricité du code à un niveau inaccessible aux enregistrements et aux objets.

    Sapere aude ! Aie le courage de te servir de ton propre entendement. Voilà la devise des Lumières.