2017-05-20 9 views
4

J'écris une bibliothèque pour gérer des images simples en ML Standard. Il devrait supporter différents types utilisés comme couleur pour chaque pixel, par ex. bool, Word8.word, etc.SML utilise abstype avec des signatures

J'ai un abstype 'a image avec toutes les fonctions communes définies indépendamment de la représentation ('a est la représentation des couleurs), mais les formats de sortie sont différents, donc je voudrais avoir différentes structures.

Existe-t-il un moyen d '"ouvrir" un abstype à l'intérieur d'une structure? Je ne peux obtenir ce travail d'une manière très laid:

abstype 'clr absimage = Image of {width : int, height : int, data : 'clr array array} 
with 
    fun createFunc (w, h) f = Image {width = w, height = h, data = ...} 
    fun createBlank (w, h) clr = createFunc (w, h) (fn _ => clr) 
    ... 
end 
signature IMAGE = sig 
    type colour 
    type image 
    val createFunc : (int * int) -> (int * int -> colour) -> image 
    val createBlank : (int * int) -> colour -> image 
    ... 
    val toBinPPM : image -> string -> unit 
end 
functor ImageFn(C : sig type colour end) = struct 
    open C 
    type image = colour absimage 
    val createFunc = createFunc 
    val createBlank = createBlank 
    ... 
end 
structure Image8 :> IMAGE = struct 
    structure T = ImageFn(struct type colour = Word8.word end) 
    open T 

    fun toBinPPM img filename = ... 
end 

En particulier, la définition du foncteur oblige à écrire des déclarations comme val name = name pour toutes les fonctions définies dans la partie with ... end de abstype.

Ou est-ce que mon approche est complètement fausse?

Cette combinaison de abstype et signature est ma tentative de recréer classe abstraite de OOP avec des méthodes communes de abstype et nécessitent la mise en œuvre d'autres méthodes dans toutes les structures utilisant la signature

post-scriptum Pourquoi SML n'autorise pas les instructions telles que open (ImageFn(struct ... end)) et force l'utilisation d'une structure temporaire (T dans le code ci-dessus)?

Répondre

5

Il n'y a aucune raison d'utiliser abstype dans le langage SML d'aujourd'hui. Considérez-le obsolète. C'est une relique des temps de pré-module. Vous pouvez obtenir le même effet en cachant les constructeurs d'un type avec des structures, des signatures et des sceaux (l'opérateur :>), mais de manière plus flexible et cohérente. Cela explique aussi pourquoi il ne s'intègre pas bien avec les modules - il les a précédés et a été essentiellement remplacé par eux.

Dans votre exemple concret, au lieu d'utiliser abstype, il suffit de définir image comme datatype directement dans le corps du foncteur ImageFn, et cacher ses constructeurs avec une annotation de signature, comme suit:

signature IMAGE = 
sig 
    type colour 
    type image 
    val createFunc : int * int -> (int * int -> colour) -> image 
    val createBlank : int * int -> colour -> image 
    ... 
end 

signature IMAGE8 = 
sig 
    include IMAGE 
    val toBinPPM : image -> string -> unit 
end 

functor ImageFn(type colour) :> IMAGE = 
struct 
    datatype image = Image of {width : int, height : int, data : colour array array} 
    fun createFunc (w, h) f = Image {width = w, height = h, data = ...} 
    fun createBlank (w, h) clr = createFunc (w, h) (fn _ => clr) 
    ... 
end 

structure Image8 :> IMAGE8 = 
struct 
    structure T = ImageFn(type colour = Word8.word) 
    open T 
    fun toBinPPM img filename = ... 
end 

Edit: En fait, il n'est même pas nécessaire dans ce cas de définir image comme type de données. Un type simple ferait tout aussi bien et rend le code un peu plus simple:

type image = {width : int, height : int, data : colour array array} 

Quant à votre question PS: oui, je ne sais pas non plus. Il n'y a pas de raison particulière. Certains dialectes SML l'implémentent en tant qu'extension.

+0

Merci beaucoup! Je n'ai pas réalisé que vous pourriez utiliser ':>' avec des foncteurs. Déclarer l'image en tant que type de données est juste quelque chose qui reste de l'ancienne implémentation qui m'a été imposée par une tâche unidentique – zlotnleo