2017-08-06 8 views
2

1) J'ai ce type de moduleComment faire correspondre sur les constructeurs de types de données abstraites OCAML

module type MOD_SIG = sig type t val min val max;; 

2) Je crée deux modules basés sur la signature ci-dessus

module MOD_UINT8 = struct 
    type t = int32 
    let min = Int32.of_int 0 
    let max = Int32.of_int 255 end;; 

module MOD_UINT32 = struct 
    type t = int64 
    let min = Int64.zero 
    let max = Int64.of_int 4294967295 end ;; 

3) J'ai créé modules de première classe de 2

let uint_8 = (module MOD_UINT8:MOD_SIG);; 
let uint_32 = (module MOD_UINT32:MOD_SIG);; 

4) Je veux écrire une fonction qui accepte un module de premier ordre en tant que arg et tente de ma tch si une valeur particulière dans ce module était de Int32 ou Int64.

tels que

let module M=(val m:MOD_SIG) in match M.t with 
    | Int32 -> "Int32" 
    | Int64 -> "Int64" 

I appris de @octachron qu'il ne soit pas possible. Bien que je voulais juste soulever cette question pour comprendre, s'il pourrait y avoir une solution de contournement?

+0

Pourriez-vous, s'il vous plaît, utiliser les outils de balisage pour mettre en évidence les blocs de code? En l'état, votre question est complètement illisible. – soupault

+0

N'oubliez pas d'accepter les réponses si elles répondent correctement à votre question, cela permet aux gens de savoir que cette question est résolue. – Lhooq

Répondre

2

Eh bien, vous pourriez peut-être ajouter à vos modules une fonction qui indique que leur valeur particulière est:

type pv = I8 | I32 | I64 

module type MOD_SIG = sig 
    type t 
    val min 
    val max 
    val which_pv : pv 
;; 

module MOD_UINT8 = struct 
    type t = int32 
    let min = Int32.of_int 0 
    let max = Int32.of_int 255 
    let which_pv = I8 
end;; 

module MOD_UINT32 = struct 
    type t = int64 
    let min = Int64.zero 
    let max = Int64.of_int 4294967295 
    let which_pv = I64 
end;; 

En fait, parfois votre fonction dépend de ce que exactement le type t est et c'est là foncteurs apparaît. Disons, par exemple, que vous voulez implémenter un module sur des nombres qui peuvent être entiers, entiers non signés, flottants ... Dans ce cas, les opérations de base dépendent du type exact et un foncteur serait mieux ici:

module type NSig = sig 
    type t 
    val zero : t 
    val one : t 
    val min : t 
    val max : t 
    val add : t -> t -> t 
    val mult : t -> t -> t 
end;; 

module MNumb (N : NSig) = struct 
    type t = N.t 
    let min = N.min 
    let max = N.max 
    let add = N.add 
    let mult = N.mult 
    let rec pow t n = 
    if n = 0 then N.one 
    else if n = 1 then t 
    else let tt = pow t (n/2) in 
     if n mod 2 = 0 then tt else mult t tt 
end;; 

Comme vous pouvez le voir, pour créer pow je dois savoir comment 1 est représenté et mult aussi, mais depuis pow n'est pas une fonction de base , je crée dans le foncteur. Il vous suffit donc de donner à votre foncteur les bases de votre type (int8, int32, int64, float, fractions ...) et de l'alimenter au foncteur pour créer les fonctions les plus avancées.

+0

J'ai compris. En général, vous pensez que le module de première classe est préférable d'accomplir ceci ou les foncteurs? –

+0

Eh bien, cela dépend de ce que vous voulez faire, en fait. Si votre fonction est spécifique au type que vous avez choisi, je dirais que les foncteurs sont meilleurs pour accomplir ceci. Laissez-moi mettre à jour ma réponse pour vous donner un aperçu de ce que je considère comme une meilleure solution. – Lhooq

+0

Donc, fondamentalement, la suggestion est d'avoir Uint8, Uint16, Uint32, Uint64 comprennent type t val zéro: t val un: t val min: t val max: t val ajouter: t -> t -> t val mult: t -> t -> t et d'utiliser des foncteurs uniquement pour ajouter une fonction avancée aux modules ci-dessus. Alors que tout ce que je veux est en fait d'avoir juste au-dessus des valeurs et des fonctions dans chacun des modules et aucune fonction avance comme pow. Donc, de ce point de vue, puis-je supposer que les foncteurs sont exagérés et que je devrais simplement créer Uint8, Uint16, Uint32, Uint64 en utilisant leur propre signature et leurs propres structures, au lieu de tirer parti des foncteurs? –