• [^] # Re: Raisons d'essayer Rust

    Posté par . En réponse au journal Retour d'expérience sur les langages de programmation. Évalué à 2.

    en fait, les interfaces de Go (qui sont des valeurs) peuvent être (et au besoin sont) utilisées exactement comme les types somme à l'aide d'un type switch (le cas courant de l'énumération se fait d'habitude avec des constantes).

    Cela peut certes être utilisé dans certain cas en lieu et place d'un type somme, mais ce n'est vraiment pas la même notion. Les interfaces, c'est les type classes de Haskell ou les traits de Rust, mais en version du pauvre. Les fonctions qui prennent un interface en paramètre c'est juste des fonctions qui prennent un paramètre implicite qui est de type produit.

    Par exemple, un type que l'on peut convertir en chaîne de caractères, on pourrait l'écrire comme cela en OCaml :

    type 'a showable = {show : 'a -> string}
    (* puis l'utiliser ainsi *)
    let print dict value = print_endline (dict.show value);;
    val print : 'a showable -> 'a -> unit = <fun>

    Ce que font les interfaces de Go, les types classes ou les traits c'est instancier implicitement le dictionnaire de méthodes en fonction du type du paramètre value. De telle sorte qu'il suffit d'écrire print 1 au lieu de print {show = string_of_int} 1. Mais un dictionnaire, cela reste un type produit. C'est surtout utilisé pour faire du polymorphisme ad hoc, et non pour se substituer au type somme.

    Pour faire la même chose en OCaml, avec la même généralité que les type classes de Haskell, il faudrait passer par le système des modules et foncteurs. Un module est un dictionnaire (type produit), qu'il faudrait passer comme argument implicite à une fonction. Il faut pour cela étendre le système des modules de première classes (en faire des valeurs comme les autres), puis ajouter un système de résolution pour arguments implicites. C'est un objet de recherche en cours.

    J'ai pas vu passer ça ! J'imagine que c'est une extension ppx, ou alors directement intégré dans le langage ?

    C'est du sucre syntaxique intégré au langage depuis la version 4.08, mais c'est inspiré de ce qui se faisait avant avec des extensions ppx. Cela a été fait pour simplifier le code qui utilise des monades ou des foncteurs applicatifs (cf. la doc sur les binding operators). Je trouve que cela rend mieux compte du choix du nom bind pour l'opérateur monadique que ne le fait la do notation de Haskell. Le >>= c'est juste une généralisation du pipe du shell qui est le bind de la monade identité.

    Le code avec les exceptions j'aurais pu l'écrire ainsi si j'avais utilisé le pipe :

    let test i j =
     int_of_string i |> fun i ->
     int_of_string j |> fun j ->
     i + j

    ou avec la type classe de la monade identité :

    let (>>=) = (|>)
    let return x = x
    let test i j =
     int_of_string i >>= fun i ->
     int_of_string j >>= fun j ->
     return (i + j)

    Ce qui est le même code que la version monadique avec le type option. Réciproquement, le sucre syntaxique des binding operators permet de récupérer la forme non monadique pour du code monadique.

    En Rust, ils se sont contentés de sucre syntaxique à l'aide d'une macro ? spécifique au cas du type option pour une erreur (type Result).

    Comme OCaml maintenant, si je comprends bien.

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