Search code examples
liststructuresmlml

ML: Is it possible to create a list of structures in SML?


I am a beginner to ML/Haskell and I am trying to create a list of structures. Actually, I am developing a web application in Urweb (functional web programming language, a lot of features from ML and Haskell.) I am trying to create an interface to Tinymce (open source rich text editor, and it consists of all the plugin such as print, link). So to manage all plugins, I am composing in the form of structure and I need one data structure to hold all the structures (Plugins in my case) and at the end stage in can be used to initialize my editor.

For example:

val plugins = [print, link, img];

and elements inside list plugins such as print is a structure:

structure print = struct
  type t = string
  .
  .
end

How can I achieve this?


Solution

  • The general answer is that No you cannot create a list of structures, the same is true as well of signatures, and functors

    however; if your plugin system is built in a way in which the entry types, and exit types of each plugin are the same across all plugins, you can build a kind of closure to a structure and embed that into a function.

    you can then use functors, to build up the functions of your plugin system

    We start out with the interface of each "plugin".

    signature DANCER =
    sig
        type t;
    
        val dancer : t
        val tired : t -> bool
        val dance : t -> t;
    end
    

    Followed by the interface through which our application interacts with the plugin.

    datatype exhaustion = Exhausted;
    
    signature DANCING_MANIA =
    sig
      val dance : unit -> exhaustion;
    end
    

    The implementation of the above DANCING_MANIA signature, accepts a DANCER, and hides the differences between plugins/structures

    functor Dancer (D : DANCER) : DANCING_MANIA =
    struct
    
      fun dance() =
        let fun until_exhaustion (dancer) =
             if not (D.tired dancer)
                then until_exhaustion(D.dance(dancer))
                else Exhausted;
         in until_exhaustion(D.dancer) end
    end
    

    Finally we can implement some plugins, and throw them in a list.

    structure Tony :> DANCER =
    struct
      type t = int;
    
      val dancer = 5;
    
      fun tired x = x <= 0;
      fun dance x = (print "tony dance!\n"; x - 1);
    end
    
    structure Annette :> DANCER =
    struct
      type t = real;
    
      val dancer = 1.0;
    
      fun tired x = x <= 0.0;
      fun dance x = (print "annette dance!\n"; x - 0.2);
    end
    structure TonyDance = Dancer(Tony);
    structure AnnetteDance = Dancer(Annette);
    
    val dancers = [TonyDance.dance, AnnetteDance.dance];
    
    fun danceOff (x::xs) = let val _ = x(); in danceOff(xs) end
      | danceOff ([]) = ();
    val _ = danceOff(dancers);
    

    So, the idea is that while you cannot create a list of structures, you can create a list of things, that each contain a different structure, as long as the exposed types are uniform.