extern crate self as prismqueer;
pub mod beam;
pub mod coincidence;
pub mod crystal;
pub mod luminosity;
pub mod scalar_loss;
pub mod substrate_ref;
pub mod trace;
pub mod connection;
pub mod content;
pub mod kernel;
pub mod merkle;
pub mod metal;
pub mod named;
pub mod oid;
pub mod optic_kind;
pub mod precision;
pub mod spectral_oid;
pub mod spectral_uuid;
pub mod store;
#[cfg(feature = "optics")]
pub mod optics;
#[cfg(feature = "pq")]
pub mod pq;
#[cfg(feature = "bundle")]
pub mod bundle;
#[cfg(feature = "lambda")]
pub mod lambda;
#[cfg(feature = "lapack")]
pub mod ffi;
#[cfg(feature = "lapack")]
pub mod spectral_dimension;
#[cfg(feature = "bundle")]
pub use bundle::{
Bundle, Closure, Connection, Cyclic, Fiber, Gauge, GroupStructure, IdentityPrism,
LawvereFixedPoint, StableFiber, Transport,
};
pub use beam::{Beam, Operation, Optic};
pub use coincidence::{canonical_hash, coincidence_hash, Detector, HashPrism};
pub use prismqueer_projections::declaration;
#[cfg(feature = "lambda")]
pub use prismqueer_projections::Lambda as DeriveLambda;
pub use prismqueer_projections::Prism as DerivePrism;
pub use scalar_loss::ScalarLoss;
pub use substrate_ref::Ref;
pub use terni::{Diagnostic, Imperfect, Loss, Metric, PropertyVerdict, Transparency};
pub use trace::{Op, Step, StepOutput, Trace, Traced};
pub use connection::{Carrier, ScalarConnection};
pub use content::ContentAddressed;
pub use crystal::Crystal;
pub use kernel::{Decomposition, KernelSpec};
pub use luminosity::Luminosity;
pub use merkle::{diff, Delta, MerkleTree};
pub use named::Named;
pub use oid::{Addressable, Oid};
pub use optic_kind::{FieldOptic, OpticKind};
pub use precision::{Precision, Pressure};
pub use spectral_oid::SpectralOid;
pub use spectral_uuid::{ParseError as SpectralUuidParseError, SpectralUuid};
pub use store::Store;
pub trait Prism {
type Input: Beam;
type Focused: Beam<In = <Self::Input as Beam>::Out>;
type Projected: Beam<In = <Self::Focused as Beam>::Out>;
type Refracted: Beam<In = <Self::Projected as Beam>::Out>;
fn focus(&self, beam: Self::Input) -> Self::Focused;
fn project(&self, beam: Self::Focused) -> Self::Projected;
fn settle(&self, beam: Self::Projected) -> Self::Refracted;
}
impl<P: Prism> Prism for &P {
type Input = P::Input;
type Focused = P::Focused;
type Projected = P::Projected;
type Refracted = P::Refracted;
fn focus(&self, beam: P::Input) -> P::Focused {
P::focus(self, beam)
}
fn project(&self, beam: P::Focused) -> P::Projected {
P::project(self, beam)
}
fn settle(&self, beam: P::Projected) -> P::Refracted {
P::settle(self, beam)
}
}
pub fn apply<P: Prism>(prism: &P, beam: P::Input) -> P::Refracted {
beam.apply(Focus(prism))
.apply(Project(prism))
.apply(Settle(prism))
}
pub fn apply_h<P, SIn, In, Out, E, L>(prism: &P, state: SIn) -> Imperfect<Out, E, L>
where
P: Prism<Input = Optic<(), SIn>, Refracted = Optic<In, Out, E, L>>,
L: Loss,
{
apply(prism, Optic::ok((), state)).into_focus()
}
pub struct Focus<P>(pub P);
pub struct Project<P>(pub P);
pub struct Settle<P>(pub P);
impl<P: Prism> Operation<P::Input> for Focus<P> {
type Output = P::Focused;
fn op(&self) -> Op {
Op::Focus
}
fn apply(self, beam: P::Input) -> P::Focused {
self.0.focus(beam)
}
}
impl<P: Prism> Operation<P::Focused> for Project<P> {
type Output = P::Projected;
fn op(&self) -> Op {
Op::Project
}
fn apply(self, beam: P::Focused) -> P::Projected {
self.0.project(beam)
}
}
impl<P: Prism> Operation<P::Projected> for Settle<P> {
type Output = P::Refracted;
fn op(&self) -> Op {
Op::Settle
}
fn apply(self, beam: P::Projected) -> P::Refracted {
self.0.settle(beam)
}
}
#[cfg(test)]
mod tests {
use super::*;
use terni::Imperfect;
struct CountPrism;
impl Prism for CountPrism {
type Input = Optic<(), String>;
type Focused = Optic<String, Vec<char>>;
type Projected = Optic<Vec<char>, usize>;
type Refracted = Optic<usize, String>;
fn focus(&self, beam: Self::Input) -> Self::Focused {
let chars: Vec<char> = beam
.result()
.ok()
.expect("focus: Err beam")
.chars()
.collect();
beam.next(chars)
}
fn project(&self, beam: Self::Focused) -> Self::Projected {
let n = beam.result().ok().expect("project: Err beam").len();
beam.next(n)
}
fn settle(&self, beam: Self::Projected) -> Self::Refracted {
let n = *beam.result().ok().expect("settle: Err beam");
beam.next(format!("{} chars", n))
}
}
fn seed(s: &str) -> Optic<(), String> {
Optic::ok((), s.to_string())
}
#[test]
fn focus_yields_chars() {
let b = CountPrism.focus(seed("hello"));
assert_eq!(b.result().ok(), Some(&vec!['h', 'e', 'l', 'l', 'o']));
assert_eq!(b.input(), &"hello".to_string());
}
#[test]
fn project_yields_count() {
let f = CountPrism.focus(seed("hello"));
let p = CountPrism.project(f);
assert_eq!(p.result().ok(), Some(&5));
}
#[test]
fn refract_produces_string() {
let f = CountPrism.focus(seed("hi"));
let p = CountPrism.project(f);
let r = CountPrism.settle(p);
assert_eq!(r.result().ok(), Some(&"2 chars".to_string()));
}
#[test]
fn operation_focus() {
let b = Focus(&CountPrism).apply(seed("hello"));
assert_eq!(b.result().ok(), Some(&vec!['h', 'e', 'l', 'l', 'o']));
}
#[test]
fn operation_project() {
let focused = CountPrism.focus(seed("hello"));
let p = Project(&CountPrism).apply(focused);
assert_eq!(p.result().ok(), Some(&5));
}
#[test]
fn operation_refract() {
let projected = seed("hi")
.apply(Focus(&CountPrism))
.apply(Project(&CountPrism));
let r = Settle(&CountPrism).apply(projected);
assert_eq!(r.result().ok(), Some(&"2 chars".to_string()));
}
#[test]
fn dsl_pipeline() {
let r = seed("hi")
.apply(Focus(&CountPrism))
.apply(Project(&CountPrism))
.apply(Settle(&CountPrism));
assert!(r.is_ok());
assert_eq!(r.result().ok(), Some(&"2 chars".to_string()));
}
#[test]
fn apply_fn_end_to_end() {
let r = apply(&CountPrism, seed("hi"));
assert!(r.is_ok());
assert_eq!(r.result().ok(), Some(&"2 chars".to_string()));
}
#[test]
fn ref_prism_works() {
let prism = CountPrism;
let r = apply(&prism, seed("abc"));
assert_eq!(r.result().ok(), Some(&"3 chars".to_string()));
}
#[test]
fn operation_op_labels() {
assert_eq!(Focus(&CountPrism).op(), Op::Focus);
assert_eq!(Project(&CountPrism).op(), Op::Project);
assert_eq!(Settle(&CountPrism).op(), Op::Settle);
}
#[test]
fn smap_as_zoom() {
let projected = seed("hello")
.apply(Focus(&CountPrism))
.apply(Project(&CountPrism));
let zoomed = projected.smap(|&n| Imperfect::success(n * 2));
assert_eq!(zoomed.result().ok(), Some(&10));
}
#[test]
fn smap_as_split() {
let projected = seed("abc")
.apply(Focus(&CountPrism))
.apply(Project(&CountPrism));
let split = projected.smap(|&n| Imperfect::success((0..n as u32).collect::<Vec<_>>()));
assert_eq!(split.result().ok(), Some(&vec![0, 1, 2]));
}
}