| Safe Haskell | Safe-Inferred |
|---|---|
| Language | Haskell2010 |
Subject.Core
Description
Core Subject data type and basic operations.
This module defines the fundamental Subject type as a self-descriptive object
with identity, labels, and property records. Subject is designed to be the
primary content type for patterns (i.e., Pattern Subject will be the common
use case) and will serialize to gram notation.
Conceptual Model: Subject as Self-Descriptive Object
A Subject is a self-descriptive object that contains:
- **Identity**: A required symbol identifier that uniquely identifies the subject within a context
- **Labels**: A set of label strings that categorize or classify the subject
- **Property Record**: A key-value map storing properties with rich value types
Subjects are "self-descriptive" because they contain all the information needed to understand and work with them: their identity (if any), their classification (labels), and their attributes (properties).
Gram Notation Mapping
Subjects correspond to the "attributes" component in gram notation patterns. Examples:
(n:Person {name:ABK})→Subject (Symbol "n") (Set.fromList [Person]) (fromList [("name", VString ABK)])(a)-[r:KNOWS {since: 2024}]->(b)→Subject (Symbol "r") (Set.fromList [KNOWS]) (fromList [("since", VInteger 2024)])[pat:Pattern {k:"v"}]→Subject (Symbol "pat") (Set.fromList [Pattern]) (fromList [("k", VString "v")])
Subject Components
Identity
The identity field is a required symbol identifier. The serialization layer will handle converting symbols to the appropriate gram notation syntax (unquoted symbols, quoted strings, or numbers).
- *Note**: While gram notation allows anonymous (unidentified) subjects, the Subject data type requires identity to be mandatory. When implementing serialization (see TODO-later.md Feature 10), we'll need to decide how to handle assigning identity to anonymous subjects during serialization.
Labels
Labels are a set of strings that categorize or classify the subject.
The set can be empty (no labels) or contain one or more unique labels.
In gram notation, labels are prefixed with : or ::. Labels are
treated as a set (no duplicates, order doesn't matter).
Examples:
Set.fromList [Person]- Single labelSet.fromList [KNOWS, RELATIONSHIP]- Multiple labelsSet.empty- No labels
Property Record
The property record is a key-value map where:
- Keys are identifiers (strings, symbols, or integers converted to strings)
- Values are
Valuetypes supporting standard and extended types
Properties store structured data about the subject. The property record can be empty (no properties) or contain any number of key-value pairs.
Integration with Pattern
Subject is designed to work as the value type for Pattern:
>>>import Pattern.Core (Pattern(..))>>>import Subject.Core (Subject(..))>>>let s = Subject (Symbol "n") (Set.fromList ["Person"]) (fromList [("name", VString "Alice")])>>>let p = Pattern { value = s, elements = [] }
This enables patterns to contain subjects as their decoration values, creating a powerful combination where patterns provide structure and subjects provide self-descriptive content.
Examples
Creating a subject with identity, labels, and properties:
>>>import Data.Map (fromList)>>>import Subject.Value (VString, VInteger)>>>let s = Subject (Symbol "n") (Set.fromList ["Person"]) (fromList [("name", VString "Alice"), ("age", VInteger 30)])
Creating a subject with only labels:
>>>let s = Subject (Symbol "n") (Set.fromList ["Person"]) empty
Creating an empty subject:
>>>let s = Subject (Symbol "") Set.empty empty
Documentation
A self-descriptive object with identity, labels, and property record.
Subject is the primary content type for patterns. It provides a structured way to represent entities with identity, classification (labels), and attributes (properties).
Subject Structure
A Subject contains three components:
identity :: Symbol- Required symbol identifierlabels :: Set String- Set of label strings (can be empty)properties :: PropertyRecord- Key-value property map
All three components are optional/flexible:
- Identity is always required (must be provided)
- Labels can be empty set
Set.empty(no labels) or contain one or more unique labels - Properties can be empty map (no properties) or contain key-value pairs
Gram Notation
Subjects correspond to the "attributes" component in gram notation:
(n:Person {name:ABK})has identityn, labelPerson, propertyname:ABK(a)-[r:KNOWS {since: 2024}]->(b)has identityr, labelKNOWS, propertysince:2024[pat:Pattern {k:"v"}]has identitypat, labelPattern, propertyk:"v"
Examples
Subject with all components:
>>>import Data.Map (fromList)>>>import Subject.Value (VString, VInteger)>>>Subject (Symbol "n") (Set.fromList ["Person"]) (fromList [("name", VString "Alice"), ("age", VInteger 30)])
Subject with only labels:
>>>Subject (Symbol "n") (Set.fromList ["Person"]) empty
Subject with only identity:
>>>Subject (Symbol "n") Set.empty empty
Integration with Pattern
Subject works as the value type for Pattern:
>>>import Pattern.Core (Pattern(..))>>>let s = Subject (Symbol "n") (Set.fromList ["Person"]) (fromList [("name", VString "Alice")])>>>let p = Pattern { value = s, elements = [] }
Constructors
| Subject | |
Fields
| |
Instances
| Monoid Subject Source # | Monoid instance for Subject. Extends the Semigroup instance by providing an identity element ( Identity SemanticsThe Monoid instance provides an identity subject:
Monoid LawsThe Monoid instance satisfies the standard monoid laws, which are verified through property-based testing in the test suite:
mempty <> s = s
s <> mempty = s ExamplesIdentity subject:
Left identity law:
Right identity law:
Using mconcat to combine subjects:
|
| Semigroup Subject Source # | Semigroup instance for Subject. Combines two subjects by merging their components:
This enables incremental subject construction using standard Haskell combinators like ExamplesCombining subjects with different components:
When first subject has default empty identity, second identity is used:
AssociativityThe operation is associative: (s1 <> s2) <> s3 = s1 <> (s2 <> s3) This is verified through property-based testing. |
| Show Subject Source # | Show instance for Subject. Provides a readable string representation of a Subject for debugging and display. The format shows all three components: identity, labels, and properties. Examples
|
| Eq Subject Source # | |
| Ord Subject Source # | |
| Hashable Subject Source # | Hashable instance for Subject. Enables using subjects as keys in Hash SemanticsThe ImplementationThe implementation follows standard Haskell conventions: hashWithSalt s (Subject ident lbls props) = s Where each component is hashed recursively using its own ExamplesHashing with default salt:
Hashing with custom salt:
|
A symbol identifier for uniquely identifying subjects.
Symbols are used as the identity component of a Subject. They provide a way to uniquely identify a subject within a context. The serialization layer will handle converting symbols to the appropriate gram notation syntax (unquoted symbols, quoted strings, or numbers).
Examples
>>>Symbol "n">>>Symbol "myId">>>Symbol "42" -- Numbers are represented as symbol strings
With OverloadedStrings extension:
>>>identity = "n" :: Symbol
Instances
| IsString Symbol Source # | |||||
Defined in Subject.Core Methods fromString :: String -> Symbol # | |||||
| Generic Symbol Source # | |||||
Defined in Subject.Core Associated Types
| |||||
| Show Symbol Source # | |||||
| Eq Symbol Source # | |||||
| Ord Symbol Source # | |||||
| Hashable Symbol Source # | |||||
| type Rep Symbol Source # | |||||
Defined in Subject.Core | |||||
type PropertyRecord = Map String Value Source #
A property record mapping keys to values.
Property records store structured data about a subject. Keys are strings
(identifiers from gram notation are converted to strings), and values
are Value types supporting standard and extended types.
Property records can be empty or contain any number of key-value pairs.
They are implemented as Map String Value for efficient lookups.
Examples
>>>import Data.Map (fromList, empty)>>>import Subject.Value (VString, VInteger)>>>fromList [("name", VString "Alice"), ("age", VInteger 30)]>>>empty -- Empty property record