Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7

- name: Cache Cargo registry
uses: actions/cache@v5
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
name: cargo clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust_check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
name: cargo check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust_coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
env:
CARGO_TERM_COLOR: always
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7

- name: Install Rust
run: rustup update stable
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust_deps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
name: cargo machete
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust_fmt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
name: cargo fmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust_miri.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
- crate: deep_causality_uncertain
extra_flags: -Zmiri-disable-isolation # open() in tests/mod.rs binary
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v7

- name: Install nightly toolchain with Miri
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/rust_release_plz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v7
with:
fetch-depth: 0 # necessary to determine the next version and build the changelog.
- name: Install Rust toolchain
Expand Down
6 changes: 2 additions & 4 deletions deep_causality_haft/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ pub(crate) mod io;
pub mod iso;
pub(crate) mod monad;
pub(crate) mod morphism;
pub(crate) mod morphism_endo;
pub(crate) mod pure;
pub(crate) mod riemann_map;
pub(crate) mod traversable;
Expand All @@ -74,7 +73,6 @@ pub use alias::alias_foldable::AliasFoldable;
pub use alias::alias_functor::AliasFunctor;
pub use alias::alias_monad::AliasMonad;
pub use alias::alias_profunctor::AliasProfunctor;

// Arrow algebra (value-level strong category: composition + the monoidal product, + builder)
pub use crate::arrow::{
Arrow, ArrowBuilder, Compose, EndoArrow, Fanout, First, Id, Lift, Second, Split, arrow,
Expand Down Expand Up @@ -108,8 +106,8 @@ pub use crate::monad::Monad;
pub use crate::monad::comonad::CoMonad;
pub use crate::monad::parametric_monad::ParametricMonad;
pub use crate::monad::promonad::Promonad;
pub use crate::morphism::{FnMorphism, Morphism};
pub use crate::morphism_endo::Endomorphism;
pub use crate::morphism::morphism_base::{FnMorphism, Morphism};
pub use crate::morphism::morphism_endo::Endomorphism;
pub use crate::pure::Pure;
pub use crate::riemann_map::RiemannMap;
pub use crate::traversable::Traversable;
Expand Down
74 changes: 2 additions & 72 deletions deep_causality_haft/src/morphism/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,75 +3,5 @@
* Copyright (c) 2023 - 2026. The DeepCausality Authors and Contributors. All Rights Reserved.
*/

use crate::{HKT2Unbound, NoConstraint, Satisfies};

/// The explicit typed-arrow base: a family of arrows `P::Type<A, B>` (think `A → B`)
/// with an identity arrow and the ability to apply an arrow to an input.
///
/// # Category Theory
///
/// `Morphism` is the object/arrow interface of a category: every discovery operator
/// (and, later, every stage of the Causal Arrow) instances it. It is parameterized by a
/// two-argument HKT witness `P: HKT2Unbound`, so the concrete carrier of an arrow is the
/// witness's `Type<A, B>`.
///
/// # Why there is no `compose` here
///
/// General arrow composition `P::Type<A, B>` with `P::Type<B, C>` into `P::Type<A, C>`
/// over *capturing* closures has no single concrete carrier under the repo's
/// `unsafe_code = "forbid"` / no-`dyn` policy (closures are unnameable unique types, and
/// `Box<dyn Fn>` is a forbidden trait object). Identity plus application is the honest,
/// implementable base, and it is enough to host the iteration combinators on
/// [`Endomorphism`](crate::Endomorphism).
pub trait Morphism<P: HKT2Unbound> {
/// The identity arrow `A → A`.
fn identity<A>() -> P::Type<A, A>
where
A: Satisfies<P::Constraint>;

/// Apply an arrow to an input, producing the output.
fn apply<A, B>(arrow: &P::Type<A, B>, input: A) -> B
where
A: Satisfies<P::Constraint>,
B: Satisfies<P::Constraint>;
}

/// The canonical function-pointer carrier for [`Morphism`]: an arrow `A → B` is a plain
/// `fn(A) -> B`.
///
/// Fully static, zero-capture, and free of `dyn`/trait objects. It covers any rule
/// expressible as a non-capturing function (for example the BRCD Meek pass, which reads
/// and writes only the graph). Rules that must capture configuration get a dedicated
/// carrier when a real call site needs one.
pub struct FnMorphism;

impl HKT2Unbound for FnMorphism {
type Constraint = NoConstraint;
type Type<A, B>
= fn(A) -> B
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>;
}

impl Morphism<FnMorphism> for FnMorphism {
#[inline]
fn identity<A>() -> <FnMorphism as HKT2Unbound>::Type<A, A>
where
A: Satisfies<NoConstraint>,
{
fn id<A>(a: A) -> A {
a
}
id::<A>
}

#[inline]
fn apply<A, B>(arrow: &<FnMorphism as HKT2Unbound>::Type<A, B>, input: A) -> B
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>,
{
(*arrow)(input)
}
}
pub(crate) mod morphism_base;
pub(crate) mod morphism_endo;
77 changes: 77 additions & 0 deletions deep_causality_haft/src/morphism/morphism_base.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* SPDX-License-Identifier: MIT
* Copyright (c) 2023 - 2026. The DeepCausality Authors and Contributors. All Rights Reserved.
*/

use crate::{HKT2Unbound, NoConstraint, Satisfies};

/// The explicit typed-arrow base: a family of arrows `P::Type<A, B>` (think `A → B`)
/// with an identity arrow and the ability to apply an arrow to an input.
///
/// # Category Theory
///
/// `Morphism` is the object/arrow interface of a category: every discovery operator
/// (and, later, every stage of the Causal Arrow) instances it. It is parameterized by a
/// two-argument HKT witness `P: HKT2Unbound`, so the concrete carrier of an arrow is the
/// witness's `Type<A, B>`.
///
/// # Why there is no `compose` here
///
/// General arrow composition `P::Type<A, B>` with `P::Type<B, C>` into `P::Type<A, C>`
/// over *capturing* closures has no single concrete carrier under the repo's
/// `unsafe_code = "forbid"` / no-`dyn` policy (closures are unnameable unique types, and
/// `Box<dyn Fn>` is a forbidden trait object). Identity plus application is the honest,
/// implementable base, and it is enough to host the iteration combinators on
/// [`Endomorphism`](crate::Endomorphism).
pub trait Morphism<P: HKT2Unbound> {
/// The identity arrow `A → A`.
fn identity<A>() -> P::Type<A, A>
where
A: Satisfies<P::Constraint>;

/// Apply an arrow to an input, producing the output.
fn apply<A, B>(arrow: &P::Type<A, B>, input: A) -> B
where
A: Satisfies<P::Constraint>,
B: Satisfies<P::Constraint>;
}

/// The canonical function-pointer carrier for [`Morphism`]: an arrow `A → B` is a plain
/// `fn(A) -> B`.
///
/// Fully static, zero-capture, and free of `dyn`/trait objects. It covers any rule
/// expressible as a non-capturing function (for example the BRCD Meek pass, which reads
/// and writes only the graph). Rules that must capture configuration get a dedicated
/// carrier when a real call site needs one.
pub struct FnMorphism;

impl HKT2Unbound for FnMorphism {
type Constraint = NoConstraint;
type Type<A, B>
= fn(A) -> B
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>;
}

impl Morphism<FnMorphism> for FnMorphism {
#[inline]
fn identity<A>() -> <FnMorphism as HKT2Unbound>::Type<A, A>
where
A: Satisfies<NoConstraint>,
{
fn id<A>(a: A) -> A {
a
}
id::<A>
}

#[inline]
fn apply<A, B>(arrow: &<FnMorphism as HKT2Unbound>::Type<A, B>, input: A) -> B
where
A: Satisfies<NoConstraint>,
B: Satisfies<NoConstraint>,
{
(*arrow)(input)
}
}
3 changes: 2 additions & 1 deletion deep_causality_haft/tests/algebra/endomorphism_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* Copyright (c) 2023 - 2026. The DeepCausality Authors and Contributors. All Rights Reserved.
*/

use deep_causality_haft::{Endomorphism, FnMorphism};
use deep_causality_haft::Endomorphism;
use deep_causality_haft::FnMorphism;

fn inc(x: i32) -> i32 {
x + 1
Expand Down
Loading
Loading