How to create a new Fact

Before you begin, you should consider:

  • what data will this new fact contain?

  • are there existing facts that contain this data?

  • how will you query your new fact?

If you are defining facts to include as part of an event (for use in asclepias, e.g.), an event’s interval is specified by the source-to-model mapping. The specification a Fact (type) is independent of the specification of the time interval that a fact (value) occurs.

Add fact as Dhall

  1. Add a new directory for your fact in src/Facts. Use CamelCase for the fact’s name.

  2. Create a file called Fact.dhall and write your new fact.

Anatomy of a Fact.dhall file

A fact’s Dhall consists of 4 key elements:

  1. a description

  2. a Type

  3. a corresponding predicate Type

  4. examples

Each of these elements are further described below, using the claim fact as an example.

This documentation does not use AsciiDoctor’s callouts. It should, but at the time of this writing, Dhall’s linter removes the end of line of comments.

Description

The description should describe how the fact should be used.

{-|
{- tag::description[] -}

= Claim

The claim fact is used to capture claim information
about an event.
This would most commonly be used in insurance claim data.

{- end::description[] -}
-}

Description text must be written:

  • in AsciiDoc syntax

  • within the Dhall comment header and enclosed by {- tag::description[] -} and {- end::description[] -},

  • include an AsciiDoc level 0 section with the fact’s name:

    = Some name

Type

A fact’s type specifies what data a fact may contain. Fact types may either be a record or a union type.

let Claim =
      { id : Text
      , claim_type : Optional Text
      , index : Optional Integer
      , procedure : Optional Text
      }

The Claim fact defined above is a record type with 4 fields, only one of which is required: id.

View example json for Claim fact
{ "id": "abcd" }
{ "id": "abcd", "claim_type": "some_type", "index": 1 }

Facts can be composed of other facts. The ClaimsFacts type includes the claim field which contains a Claim fact:

let claim = ../Claim/Fact.dhall
let combine_examples =
      (../../utils/example_utils.dhall).combine_2example_components

let make_pred_optional = (../../utils/example_utils.dhall).make_pred_optional

let ClaimFacts =

The ServiceLocation fact is an example of union type, in this case simply enumerating the possible locations:

let ServiceLocation = < Inpatient | Outpatient >

The TNValue fact in an example of union type which contains values. This fact specifies that a value of its type must either be a TextValue containing Text or a NumberValue containing a number.

let TNValue = < NumberValue : Double | TextValue : Text >

The Dhall types are used to automatically generate Haskell types, so the types need to conform to Haskell requirements. Specifically,

  • The word type cannot be used as a record key.

  • Names of union type variants must start with a capital letter. For example, this will successfully generate Haskell code:

    < Foo : Text | Bar >

    while this will not:

    < Foo : Text | bar >

PredCons Type

Every fact type has a corresponding predicate constructor (PredCons) type. This type specifies how predicates of the fact type are defined based on the predicate logic. This type is used by notionate and concipio for tagging event data.

The Claim fact, for example, specifies that predicates may only be defined on the claim_type field:

let ClaimPredCons = { claim_type : Optional (List Text) }
Future versions of the fact-models packages may automatically derive the predicate constructor shape(s). For now, it must be defined by the developer.

Examples

Each fact file must contain examples of values of the fact, predicate constructors of the fact, and the value (True or False) of what the predicate should return for a given fact. See the complete fact an example.

let exampleFact1
    : Claim
    = { id = "foo"
      , claim_type = None Text
      , index = Some +7
      , procedure = None Text
      }
The fact-models utilities contains Dhall functions for combining facts from other facts. TODO: give an example
At least one example is required; more examples are highly encouraged.

Complete fact

{-|
{- tag::description[] -}

= Claim

The claim fact is used to capture claim information
about an event.
This would most commonly be used in insurance claim data.

{- end::description[] -}
-}
let Fact = ../../utils/Fact.dhall

let Claim =
      { id : Text
      , claim_type : Optional Text
      , index : Optional Integer
      , procedure : Optional Text
      }

let ClaimPredCons = { claim_type : Optional (List Text) }

let exampleFact1
    : Claim
    = { id = "foo"
      , claim_type = None Text
      , index = Some +7
      , procedure = None Text
      }

let exampleFact2
    : Claim
    = { id = "foo"
      , claim_type = Some "notbar"
      , index = Some +7
      , procedure = None Text
      }

let examplePredCons1
    : ClaimPredCons
    = { claim_type = None (List Text) }

let examplePredCons2
    : ClaimPredCons
    = { claim_type = Some [ "bar" ] }

in  Fact
      Claim
      ClaimPredCons
      { shouldbe = True, notion = examplePredCons1, fact = exampleFact1 }
      [ { shouldbe = False, notion = examplePredCons2, fact = exampleFact1 }
      , { shouldbe = False, notion = examplePredCons2, fact = exampleFact2 }
      ]
Once you have created your Fact.dhall files, you may submit a merge request and ask that a member of dev team assist with the remaining tasks.
  • add entry for fact in fact-models/src/Facts/package.dhall

Implement a fact in Haskell

TODO

  • add entry for fact in fact-models/src/package.dhall in fact-srcs object

  • uses Dhall template haskell package

Implement a fact in Rust

TODO

  • implement fact in mod.rs in same directory as Fact.dhall

  • reexport new rust module in Facts/mod.rs

Add Fact to documentation

  • update docs/modules/models/pages/facts.adoc.

Release packages

  • bump version