jeudi 21 février 2019

Implementation of construction + view pattern example

Was working through an example of a design pattern called Constructor + View by the author that was explained through types but was having trouble figuring out the implementation.

This is the module signature:

module User : {
  type t;
  type view = { name: string, age: int };
  let make: (~name:string, ~age:int) => option(t);
  let view: t => view;
};

So User.t is hidden but from one function you can pattern match the user record

At first was thinking User.t and User.view could have the same fields:

module User: {
  type t;
  type view = { name: string, age: int, };
  let make: (~name: string, ~age: int) => option(t);
  let view: t => view;
} = {
  type t = { name: string, age: int, };
  type view = { name: string, age: int, };
  let make = (~name, ~age) => Some({name, age});
  let view = t => {name: t.name, age: t.age};
};

But got an error that looks like it can't tell the difference between view and t:

  Values do not match:
    let make: (~name: string, ~age: int) => option(view)
  is not included in
    let make: (~name: string, ~age: int) => option(t)

Tried a couple more things, the first just taking out make and trying to get the view function to work but same issue:

module User: {
  type t;
  type view = { name: string, age: int, };
  let view: t => view;
} = {
  type t = { name: string, age: int, };
  type view = { name: string, age: int, };
  let view = t => {name: t.name, age: t.age};
};

with error:

  Values do not match:
    let view: view => view
  is not included in
    let view: t => view

The second try was for having the view type be a subset of the fields (which was the use case I was hoping to use this pattern) but this has the same error as above:

module User: {
  type t;
  type view = { name: string, age: int, };
  let view: t => view;
} = {
  type t = { name: string, age: int, email: string };
  type view = { name: string, age: int, };
  let view = t => {name: t.name, age: t.age};
};

My question here is if there's a way to implement something to fit the first module signature with User.view being the same fields or subset of fields as User.t? Can make it work if the records have different fields or if I separate the records by modules but curious about that specific use case.

Aucun commentaire:

Enregistrer un commentaire