diff --git a/examples/src/main/java/uk/gov/gchq/magmacore/examples/functional/FunctionalProgrammingExample.java b/examples/src/main/java/uk/gov/gchq/magmacore/examples/functional/FunctionalProgrammingExample.java
new file mode 100644
index 00000000..fbe42d1c
--- /dev/null
+++ b/examples/src/main/java/uk/gov/gchq/magmacore/examples/functional/FunctionalProgrammingExample.java
@@ -0,0 +1,301 @@
+package uk.gov.gchq.magmacore.examples.functional;
+
+import java.time.Instant;
+import java.util.UUID;
+import java.util.function.Function;
+
+import uk.gov.gchq.magmacore.hqdm.model.Activity;
+import uk.gov.gchq.magmacore.hqdm.model.ClassOfPerson;
+import uk.gov.gchq.magmacore.hqdm.model.KindOfActivity;
+import uk.gov.gchq.magmacore.hqdm.model.Person;
+import uk.gov.gchq.magmacore.hqdm.model.PointInTime;
+import uk.gov.gchq.magmacore.hqdm.model.Role;
+import uk.gov.gchq.magmacore.hqdm.model.StateOfPerson;
+import uk.gov.gchq.magmacore.hqdm.rdf.iri.HQDM;
+import uk.gov.gchq.magmacore.hqdm.rdf.iri.IRI;
+import uk.gov.gchq.magmacore.hqdm.rdf.iri.IriBase;
+import uk.gov.gchq.magmacore.hqdm.rdf.iri.RDFS;
+import uk.gov.gchq.magmacore.hqdm.services.ClassServices;
+import uk.gov.gchq.magmacore.hqdm.services.SpatioTemporalExtentServices;
+import uk.gov.gchq.magmacore.service.MagmaCoreService;
+import uk.gov.gchq.magmacore.service.MagmaCoreServiceFactory;
+
+/**
+ * A Functional Programming example for using MagmaCore.
+ *
+ *
+ * The purpose of this example is to try to write a program that is more readable than the other examples.
+ * The {@link #main() main} method shows a clear sequence of steps carried out by the use case, and it
+ * should be possible to write the steps as reusable and composable functions.
+ *
+ */
+public class FunctionalProgrammingExample {
+
+ /**
+ * A program showing how to use functional programming with MagmaCore.
+ */
+ public static void main(final String[] args) {
+
+ /*
+ * Use function composition to build up a program that we will run later.
+ * The program will use a Context object to keep track of entities that
+ * are created. All functions in the processing chain accept a Context,
+ * mutate it, then return it. Ideally a `record` would be used instead
+ * and Lombok could be used to add 'wither' methods so that the Context
+ * could be immutable.
+ */
+ final Function program =
+
+ /*
+ * First create a MagmaCoreService in the Context.
+ */
+ createMagmaCoreService
+
+ /*
+ * The first transaction will populate the Reference Data needed by this example.
+ * Normally such data will already exist in the database and this step will not
+ * be necessary.
+ */
+ .andThen(beginWriteTransaction)
+ .andThen(populateRefData)
+ .andThen(commitTransaction)
+
+ /*
+ * Often a program will need to look up some existing entities for Reference
+ * Data needed by the use case. In this case they are stored in the Context.
+ */
+ .andThen(beginReadTransaction)
+ .andThen(findRefData)
+ .andThen(commitTransaction)
+
+ /*
+ * New entities can be created making use of the Reference Data. No transaction
+ * is needed since the entities will be persisted at the end.
+ */
+ .andThen(createPerson)
+ .andThen(createResearchActivity)
+ .andThen(createPersonAsParticipantInActivity)
+
+ /*
+ * The last transaction persists all of the new entities.
+ */
+ .andThen(beginWriteTransaction)
+ .andThen(creatEntities)
+ .andThen(commitTransaction);
+
+ /*
+ * Now execute the program created above.
+ */
+ final Context ctx = program.apply(new Context());
+
+ /*
+ * Check that the results are as expected.
+ */
+ if (ctx.magmaCore.get(ctx.person.getId()) == null) {
+ System.err.println("Cannot find person object with IRI: " + ctx.person.getId());
+ }
+ if (ctx.magmaCore.get(ctx.researchActivity.getId()) == null) {
+ System.err.println("Cannot find researchActivity object with IRI: " + ctx.researchActivity.getId());
+ }
+ if (ctx.magmaCore.get(ctx.startOfResearch.getId()) == null) {
+ System.err.println("Cannot find startOfResearch object with IRI: " + ctx.startOfResearch.getId());
+ }
+ if (ctx.magmaCore.get(ctx.stateOfPerson.getId()) == null) {
+ System.err.println("Cannot find stateOfPerson object with IRI: " + ctx.stateOfPerson.getId());
+ }
+ }
+
+ /**
+ * A class to hold the entities created and referenced by the use case.
+ *
+ *
+ * All fields are public for ease of access and to reduce clutter from
+ * adding getters and setters. Lombok could be used to generate them
+ * without adding clutter.
+ *
+ */
+ private static class Context {
+ public MagmaCoreService magmaCore;
+
+ // New entities to be created.
+ public Activity researchActivity;
+ public Person person;
+ public PointInTime startOfResearch;
+ public StateOfPerson stateOfPerson;
+
+ // Ref data items.
+ public ClassOfPerson researchersClass;
+ public KindOfActivity researchActivityKind;
+ public Role researchRole;
+ }
+
+ /**
+ * An IRI prefix for the example.
+ */
+ private static final IriBase TEST_BASE = new IriBase("test", "http://example.com/test#");
+
+ /**
+ * A class name for collecting together persons who are reseaechers.
+ */
+ private static final String RESEARCHERS_CLASS_ENTITY_NAME = "Researchers";
+
+ /**
+ * The name of a kind of activity.
+ */
+ private static final String RESEARCH_ACTIVITY_KIND_ENTITY_NAME = "Research Activities";
+
+ /**
+ * The name of a role for participants of research activities.
+ */
+ private static final String RESEARCHER_ROLE_ENTITY_NAME = "Researcher Role";
+
+ /**
+ * A function to create the MagmaCoreService. In this case it is an in-memory
+ * database for the example.
+ */
+ private static final Function createMagmaCoreService = ctx -> {
+ ctx.magmaCore = MagmaCoreServiceFactory.createWithJenaDatabase();
+ return ctx;
+ };
+
+ /**
+ * A function to persist the new entities in the database.
+ */
+ private static final Function creatEntities = ctx -> {
+ ctx.magmaCore.create(ctx.person);
+ ctx.magmaCore.create(ctx.researchActivity);
+ ctx.magmaCore.create(ctx.startOfResearch);
+ ctx.magmaCore.create(ctx.stateOfPerson);
+ return ctx;
+ };
+
+ /**
+ * A function to find the Reference Data required by this use case.
+ */
+ private static final Function findRefData = ctx -> {
+ ctx.researchActivityKind = ctx.magmaCore.findByEntityName(RESEARCH_ACTIVITY_KIND_ENTITY_NAME);
+ ctx.researchRole = ctx.magmaCore.findByEntityName(RESEARCHER_ROLE_ENTITY_NAME);
+ ctx.researchersClass = ctx.magmaCore.findByEntityName(RESEARCHERS_CLASS_ENTITY_NAME);
+ return ctx;
+ };
+
+ /**
+ * A function to create a Person.
+ */
+ private static final Function createPerson = ctx -> {
+
+ /*
+ * Create a Person.
+ */
+ ctx.person = SpatioTemporalExtentServices
+ .createPerson(randomIri());
+ ctx.person.addValue(HQDM.MEMBER_OF, ctx.researchersClass.getId());
+ return ctx;
+ };
+
+ /**
+ * A function to create an Activity.
+ */
+ private static final Function createResearchActivity = ctx -> {
+ /*
+ * Create a timestamp for use as the beginning of the axctivity.
+ */
+ final String now = Instant.now().toString();
+
+ /*
+ * Create a PointInTime event.
+ */
+ ctx.startOfResearch = SpatioTemporalExtentServices
+ .createPointInTime(randomIri());
+ ctx.startOfResearch.addValue(HQDM.VALUE_, now);
+
+ /*
+ * Create the Activity.
+ */
+ ctx.researchActivity = SpatioTemporalExtentServices
+ .createActivity(randomIri());
+ ctx.researchActivity.addValue(HQDM.BEGINNING, ctx.startOfResearch.getId());
+ ctx.researchActivity.addValue(HQDM.MEMBER_OF_KIND, ctx.researchActivityKind.getId());
+ return ctx;
+ };
+
+ /**
+ * A function to add a state of person as a participant in the research activity.
+ */
+ private static final Function createPersonAsParticipantInActivity = ctx -> {
+ /*
+ * The state of person will be a participant in the research activity.
+ */
+ ctx.stateOfPerson = SpatioTemporalExtentServices
+ .createStateOfPerson(randomIri());
+ ctx.stateOfPerson.addValue(HQDM.BEGINNING, ctx.startOfResearch.getId());
+ ctx.stateOfPerson.addValue(HQDM.MEMBER_OF_KIND, ctx.researchRole.getId());
+ ctx.stateOfPerson.addValue(HQDM.PARTICIPANT_IN, ctx.researchActivity.getId());
+ ctx.stateOfPerson.addValue(HQDM.TEMPORAL_PART_OF, ctx.person.getId());
+ ctx.stateOfPerson.addValue(RDFS.RDF_TYPE, HQDM.PARTICIPANT);
+
+ return ctx;
+ };
+
+ /**
+ * A utility function to generate random IRI values.
+ */
+ private static final IRI randomIri() {
+ return new IRI(TEST_BASE, UUID.randomUUID().toString());
+ }
+
+ /**
+ * A function to populate Reference Data for the example.
+ */
+ private static Function populateRefData = ctx -> {
+
+ /*
+ * Create a Class of Person.
+ */
+ final ClassOfPerson cop = ClassServices.createClassOfPerson(randomIri());
+ cop.addValue(HQDM.ENTITY_NAME, RESEARCHERS_CLASS_ENTITY_NAME);
+ ctx.magmaCore.create(cop);
+
+ /*
+ * Create a Kind of Activity.
+ */
+ final KindOfActivity koa = ClassServices.createKindOfActivity(randomIri());
+ koa.addValue(HQDM.ENTITY_NAME, RESEARCH_ACTIVITY_KIND_ENTITY_NAME);
+ ctx.magmaCore.create(koa);
+
+ /*
+ * Create a Role.
+ */
+ final Role role = ClassServices.createRole(randomIri());
+ role.addValue(HQDM.ENTITY_NAME, RESEARCHER_ROLE_ENTITY_NAME);
+ ctx.magmaCore.create(role);
+
+ return ctx;
+ };
+
+ /**
+ * A function to begin a read transaction.
+ */
+ private static final Function beginReadTransaction = magmaCore -> {
+ magmaCore.magmaCore.beginWrite();
+ return magmaCore;
+ };
+
+ /**
+ * A function to begin a write transaction.
+ */
+ private static final Function beginWriteTransaction = magmaCore -> {
+ magmaCore.magmaCore.beginWrite();
+ return magmaCore;
+ };
+
+ /**
+ * A function to commit a transaction.
+ */
+ private static final Function commitTransaction = magmaCore -> {
+ magmaCore.magmaCore.commit();
+ return magmaCore;
+ };
+
+}
+
diff --git a/examples/src/test/java/uk/gov/gchq/magmacore/examples/functional/FunctionalProgrammingExampleTest.java b/examples/src/test/java/uk/gov/gchq/magmacore/examples/functional/FunctionalProgrammingExampleTest.java
new file mode 100644
index 00000000..41833990
--- /dev/null
+++ b/examples/src/test/java/uk/gov/gchq/magmacore/examples/functional/FunctionalProgrammingExampleTest.java
@@ -0,0 +1,18 @@
+package uk.gov.gchq.magmacore.examples.functional;
+
+import org.junit.Test;
+
+/**
+ * Execute the Functional Programming example for using MagmaCore.
+ */
+public class FunctionalProgrammingExampleTest {
+
+ /**
+ * A unit test to ensure that the FunctionalProgrammingExample code is executed as part of a build.
+ */
+ @Test
+ public void test() {
+ FunctionalProgrammingExample.main(null);
+ }
+}
+