Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7533951
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 30, 20262026-05-30T05:52:33+00:00 2026-05-30T05:52:33+00:00

Right now, I have a working HTML template system written in OCaml. The general

  • 0

Right now, I have a working HTML template system written in OCaml. The general design is that an individual template is a module returned by a functor applied to the following module type:

module type TEMPLATE_DEF = sig
  type t (* The type of the data rendered by the template. *)
  val source : string (* Where the HTML template itself resides. *)
  val mapping : (string * (t -> string)) list 
end

For example, rendering a blog post would be based on this:

module Post = Loader.Html(struct
  type t = < body : string ; title : string >
  let source  = ...
  let mapping = [ "body", (fun x -> x#body) ; "title", (fun x -> x#title) ]
end)

It is more complex that just having a t -> (string * string) list function that extracts all possible values, but it ensures during initialization that all the required template variables are provided.

Adding a new field, such as permalink, is trivial but involves manually editing the code. I am trying to move away from this process and towards a situation where anything permalink-related throughout the application is cleanly compartimented away in a module and merely applied wherever it should be used.

This led me initially to a decorator pattern along the lines of:

module WithPermalink = functor(Def:TEMPLATE_DEF) -> struct
  type t = < permalink : string ; inner : Def.t >
  let source = Def.source 
  let mapping =
    ( "permalink", (fun x -> x # permalink) ) 
    :: List.map (fun (k,f) -> (k, (fun x -> f (x#inner)))) Def.mapping 
end

However, this approach is still unsatisfying for two reasons, and I am looking for a better pattern to solve them both.

The first problem is that this approach still requires me to change the template definition code (I still have to apply the WithPermalink functor). I would like a solution where adding the permalink to template Post would be performed non-intrusively by the Permalink module (this will probably involve implementing some sort of generic extensibility of the template system).

The second problem is that if I need to apply several such functors (having a date, tags, comments…) then the order in which they are applied becomes relevant to the data type and thus to any code using it. This does not prevent code from working, but it’s frustrating to have a by definition commutative operation be non-commutative in its implementation.

How can I achieve this ?

EDIT

After giving the subject more thought, I’ve settled on an extensible-object design. This is how I expect it would look after some preprocessor beautification :

(* Module Post *)
type post = {%
  title : string = "" ;
  body  : string = "" 
%}   

let mapping : (string * (post -> string)) list ref = 
  [ "title", (%title) ;
    "body",  (%body) ]

(* Module Permalink *)
type %extend Post.post = {% 
  link : string = "" 
%}

Post.mapping := ("permalink", (%link)) :: !Post.mapping

(* Defining the template *)
module BlogPost = Loader.Html(struct
  type t = Post.post
  let source = ...
  let mapping _ = !Post.mapping
end)

(* Creating and editing a post *)
let post = {% new Post.post with 
  Post.title     = get_title () ;
  Post.body      = get_body () ;
  Permalink.link = get_permalink () ; 
%}

let post' = {% post with title = BatString.strip (post % Post.title) %}

The implementation would be fairly standard : when an extensible type post is defined, create a ExtenderImplementation_post module at that spot with this kind of code :

module ExtenderImplementation_post : sig
  type t 
  val field : 'a -> (t,'a) lens
  val create : unit -> t
end = struct
  type t = (unit -> unit) array
  let fields : t ref = ref [| |]
  let field default =
    let store = ref None in
    let ctor () = store := Some default in
    let n = Array.length !fields in
    fields := Array.init (n+1) (fun i -> if i = n then ctor else (!fields).(i)) ;
    { lens_get = (fun (t:t) -> t.(n) () ; match !store with
      | None   -> assert false
      | Some s -> store := None ; s) ;
      lens_set = (fun x (t:t) -> let t' = Array.copy t in
                            t'.(n) <- (fun () -> store := Some x) ; t') }
  let create () = !fields
end
type post = ExtenderImplementation_post.t

Then, defining a field link : string = "" is translated to :

let link : (Post.post,string) lens = Post.ExtenderImplementation_post.extend "" 

The translation of getters, setters and initialization are fairly straightforward, and use the fact that fields are actually lenses.

Do you see any potential design issues or possible extensions to this approach ?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-30T05:52:35+00:00Added an answer on May 30, 2026 at 5:52 am

    What you want to avoid is writing the boilerplate around the labels you are defining. Maybe you could just use camlp4 to automatically generate the module code for a set of labels ?

    Edit

    You want to be able to add a method to an object type. I don’t think it is currently possible.

    The only possible way I am aware of is to use a pre-processor that would be type-aware. In Haskell, they have HaskellTemplate, a pre-processor that expand macros during typing, with the knowledge of the typing environment.

    I wrote a prototype of the equivalent for OCaml two years ago, it was working well, it is reachable here for ocaml-3.12.0, with some basic examples. But to do what you want, you need to understand the OCaml AST and be able to generate a new AST from the previous one (there are currently no quotations to easily generate ASTs).

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm working on a C# program, and right now I have one Form and
I'm currently working on web application using VB in ASP.NET. Right now I have
Hi! I have a working prototype of a game engine and right now I'm
I am working on an app right now where I have Individuals, Athletes and
It doesn't seem to be working right now. I get a java.lang.NullPointerException I have
I have created some tests in my WPF application. Right now I am working
I'm working in C, and I have to concatenate a few things. Right now
Right now I have an SSIS package that runs every morning and gives me
Let say you are working on a website template that has many pages (index.html,
I am working on developing a drupal site right now. I have created a

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.