tamer: f::{Functor=>Map}: It's not really a functor

At least not how most people expect functors to be.  I'm really just using
this as a map with powerful inference properties that make writing code more
pleasent.

And I need fallible methods now too.

DEV-13163
main
Mike Gerwitz 2023-07-26 16:43:09 -04:00
parent e14854a555
commit 38c0161257
17 changed files with 42 additions and 44 deletions

View File

@ -36,7 +36,7 @@ use super::{
use crate::{
diagnose::Annotate,
diagnostic_unreachable,
f::Functor,
f::Map,
parse::{prelude::*, StateStack},
span::Span,
sym::SymbolId,
@ -1310,7 +1310,7 @@ impl<T> AsRef<T> for EnvScopeKind<T> {
}
}
impl<T, U> Functor<T, U> for EnvScopeKind<T> {
impl<T, U> Map<T, U> for EnvScopeKind<T> {
type Target = EnvScopeKind<U>;
fn map(self, f: impl FnOnce(T) -> U) -> Self::Target {

View File

@ -31,7 +31,7 @@ use super::{
};
use crate::{
asg::{graph::object::ObjectIndexTo, ObjectKind},
f::Functor,
f::Map,
parse::prelude::*,
};

View File

@ -29,7 +29,7 @@ use self::object::{
use super::{AsgError, Object, ObjectIndex, ObjectKind};
use crate::{
diagnose::{panic::DiagnosticPanic, Annotate, AnnotatedSpan},
f::Functor,
f::Map,
global,
span::Span,
};

View File

@ -123,7 +123,7 @@ use super::{Asg, AsgError};
use crate::{
diagnose::{panic::DiagnosticPanic, Annotate, AnnotatedSpan},
diagnostic_panic,
f::Functor,
f::Map,
parse::util::SPair,
span::{Span, UNKNOWN_SPAN},
};
@ -924,7 +924,7 @@ impl ObjectIndex<Object> {
}
}
impl<O: ObjectKind> Functor<Span> for ObjectIndex<O> {
impl<O: ObjectKind> Map<Span> for ObjectIndex<O> {
fn map(self, f: impl FnOnce(Span) -> Span) -> Self {
match self {
Self(index, span, ph) => Self(index, f(span), ph),

View File

@ -20,7 +20,7 @@
//! Expressions on the ASG.
use super::{prelude::*, Doc, Ident, ObjectIndexTo, Tpl};
use crate::{f::Functor, num::Dim, span::Span};
use crate::{f::Map, num::Dim, span::Span};
use std::fmt::Display;
#[cfg(doc)]
@ -52,7 +52,7 @@ impl Expr {
}
}
impl Functor<Span> for Expr {
impl Map<Span> for Expr {
fn map(self, f: impl FnOnce(Span) -> Span) -> Self {
match self {
Self(op, dim, span) => Self(op, dim, f(span)),

View File

@ -23,7 +23,7 @@ use super::{prelude::*, Expr, Meta, Pkg, Tpl};
use crate::{
diagnose::{panic::DiagnosticPanic, Annotate, Diagnostic},
diagnostic_todo,
f::Functor,
f::Map,
fmt::{DisplayWrapper, TtQuote},
num::{Dim, Dtype},
parse::{util::SPair, Token},

View File

@ -36,7 +36,7 @@ use super::{prelude::*, Doc, Ident};
use crate::{
diagnose::Annotate,
diagnostic_todo,
f::Functor,
f::Map,
fmt::{DisplayWrapper, TtQuote},
parse::{util::SPair, Token},
span::Span,
@ -156,7 +156,7 @@ impl Display for Meta {
}
}
impl Functor<Span> for Meta {
impl Map<Span> for Meta {
fn map(self, f: impl FnOnce(Span) -> Span) -> Self::Target {
match self {
Self::Required(span) => Self::Required(f(span)),

View File

@ -21,7 +21,7 @@
use super::{prelude::*, Doc, Ident, Tpl};
use crate::{
f::Functor,
f::Map,
fmt::{DisplayWrapper, TtQuote},
parse::{util::SPair, Token},
span::Span,
@ -87,7 +87,7 @@ impl Display for Pkg {
}
}
impl Functor<Span> for Pkg {
impl Map<Span> for Pkg {
fn map(self, f: impl FnOnce(Span) -> Span) -> Self::Target {
match self {
Self(span, path) => Self(f(span), path),

View File

@ -30,7 +30,7 @@ use crate::{
graph::{object::Tpl, AsgRelMut},
Asg, AsgError,
},
f::Functor,
f::Map,
span::Span,
};
use std::{fmt::Display, marker::PhantomData};
@ -481,7 +481,7 @@ impl DynObjectRel<ObjectIndex<Object>, ObjectIndex<Object>> {
}
}
impl<S, T, U, V> Functor<(S, T), (U, V)> for DynObjectRel<S, T> {
impl<S, T, U, V> Map<(S, T), (U, V)> for DynObjectRel<S, T> {
type Target = DynObjectRel<U, V>;
fn map(self, f: impl FnOnce((S, T)) -> (U, V)) -> Self::Target {

View File

@ -22,7 +22,7 @@
use std::fmt::Display;
use super::{prelude::*, Doc, Expr, Ident};
use crate::{f::Functor, parse::util::SPair, span::Span};
use crate::{f::Map, parse::util::SPair, span::Span};
/// Template with associated name.
#[derive(Debug, PartialEq, Eq)]
@ -46,7 +46,7 @@ impl Tpl {
}
}
impl Functor<Span> for Tpl {
impl Map<Span> for Tpl {
fn map(self, f: impl FnOnce(Span) -> Span) -> Self::Target {
match self {
Self(span, shape) => Self(f(span), shape),
@ -54,7 +54,7 @@ impl Functor<Span> for Tpl {
}
}
impl Functor<TplShape> for Tpl {
impl Map<TplShape> for Tpl {
fn map(self, f: impl FnOnce(TplShape) -> TplShape) -> Self::Target {
match self {
Self(span, shape) => Self(span, f(shape)),

View File

@ -24,7 +24,7 @@ use crate::{
graph::object::ObjectRelTy,
ExprOp,
},
f::Functor,
f::Map,
parse::{
util::{spair, SPair},
ParseState,

View File

@ -33,11 +33,12 @@
/// A type providing a `map` function from inner type `T` to `U`.
///
/// In an abuse of terminology,
/// this functor is polymorphic over the entire trait,
/// This used to be called `Functor`,
/// but was renamed because it was an abuse of terminology;
/// this is polymorphic over the entire trait,
/// rather than just the definition of `map`,
/// allowing implementations to provide multiple specialized `map`s
/// without having to define individual `map_*` methods.
/// allowing implementations to provide multiple specialized `map`s
/// without having to define individual `map_*` methods.
/// Rust will often be able to infer the proper types and invoke the
/// intended `map` function within a given context,
/// but methods may still be explicitly disambiguated using the
@ -46,16 +47,13 @@
/// if a functor requires a monomorphic function
/// (so `T = U`),
/// then it's not really a functor.
/// We'll refer to these structures informally as monomorphic functors,
/// since they provide the same type of API as a functor,
/// but cannot change the underlying type.
///
/// This trait also provides a number of convenience methods that can be
/// implemented in terms of [`Functor::map`].
/// implemented in terms of [`Map::map`].
///
/// Why a primitive `map` instead of `fmap`?
/// ========================================
/// One of the methods of this trait is [`Functor::fmap`],
/// One of the methods of this trait is [`Map::fmap`],
/// which [is motivated by Haskell][haskell-functor].
/// This trait implements methods in terms of [`map`](Self::map) rather than
/// [`fmap`](Self::fmap) because `map` is a familiar idiom in Rust and
@ -66,8 +64,8 @@
/// which is additional boilerplate relative to `map`.
///
/// [haskell-functor]: https://hackage.haskell.org/package/base/docs/Data-Functor.html
pub trait Functor<T, U = T>: Sized {
/// Type of object resulting from [`Functor::map`] operation.
pub trait Map<T, U = T>: Sized {
/// Type of object resulting from [`Map::map`] operation.
///
/// The term "target" originates from category theory,
/// representing the codomain of the functor.
@ -83,7 +81,7 @@ pub trait Functor<T, U = T>: Sized {
/// all others are implemented in terms of it.
fn map(self, f: impl FnOnce(T) -> U) -> Self::Target;
/// Curried form of [`Functor::map`],
/// Curried form of [`Map::map`],
/// with arguments reversed.
///
/// `fmap` returns a unary closure that accepts an object of type
@ -106,22 +104,22 @@ pub trait Functor<T, U = T>: Sized {
///
/// This is intended for cases where there's a single element that will
/// be replaced,
/// taking advantage of [`Functor`]'s trait-level polymorphism.
/// taking advantage of [`Map`]'s trait-level polymorphism.
fn overwrite(self, value: U) -> Self::Target {
self.map(|_| value)
}
/// Curried form of [`Functor::overwrite`],
/// Curried form of [`Map::overwrite`],
/// with arguments reversed.
fn foverwrite(value: U) -> impl FnOnce(Self) -> Self::Target {
move |x| x.overwrite(value)
}
}
impl<T, U> Functor<T, U> for Option<T> {
impl<T, U> Map<T, U> for Option<T> {
type Target = Option<U>;
fn map(self, f: impl FnOnce(T) -> U) -> <Self as Functor<T, U>>::Target {
fn map(self, f: impl FnOnce(T) -> U) -> <Self as Map<T, U>>::Target {
Option::map(self, f)
}
}

View File

@ -57,7 +57,7 @@ mod tplshort;
use crate::{
diagnose::{Annotate, Diagnostic},
f::Functor,
f::Map,
fmt::{DisplayWrapper, TtQuote},
parse::{util::SPair, Object, Token},
span::Span,
@ -228,7 +228,7 @@ impl Nir {
}
}
impl Functor<SymbolId> for Nir {
impl Map<SymbolId> for Nir {
/// Map over a token's [`SymbolId`].
///
/// This allows modifying a token's [`SymbolId`] while retaining the

View File

@ -108,7 +108,7 @@ use memchr::memchr2;
use super::{Nir, NirEntity};
use crate::{
diagnose::{panic::DiagnosticPanic, Annotate, AnnotatedSpan, Diagnostic},
f::Functor,
f::Map,
fmt::{DisplayWrapper, TtQuote},
parse::{prelude::*, util::SPair, NoContext},
span::Span,

View File

@ -26,7 +26,7 @@
//! to use outside of the domain of the parsing system itself.
use super::{prelude::*, state::TransitionData};
use crate::{f::Functor, span::Span, sym::SymbolId};
use crate::{f::Map, span::Span, sym::SymbolId};
use std::fmt::Display;
/// A [`SymbolId`] with a corresponding [`Span`].
@ -83,7 +83,7 @@ impl SPair {
}
}
impl Functor<SymbolId> for SPair {
impl Map<SymbolId> for SPair {
/// Map over the [`SymbolId`] of the pair while retaining the original
/// associated [`Span`].
///
@ -98,7 +98,7 @@ impl Functor<SymbolId> for SPair {
}
}
impl Functor<Span> for SPair {
impl Map<Span> for SPair {
/// Map over the [`Span`] of the pair while retaining the associated
/// [`SymbolId`].
///

View File

@ -101,7 +101,7 @@ use super::{
CloseSpan, OpenSpan, QName,
};
use crate::{
f::Functor,
f::Map,
parse::prelude::*,
span::{Span, UNKNOWN_SPAN},
xir::EleSpan,

View File

@ -46,7 +46,7 @@ use super::{
CloseSpan, OpenSpan, QName, Token as XirToken, TokenStream,
};
use crate::{
f::Functor,
f::Map,
parse::prelude::*,
span::Span,
sym::{st::is_common_whitespace, GlobalSymbolResolve, SymbolId},
@ -248,7 +248,7 @@ impl<T: TextType> From<Attr> for XirfToken<T> {
}
}
impl<T: TextType> Functor<Depth> for XirfToken<T> {
impl<T: TextType> Map<Depth> for XirfToken<T> {
fn map(self, f: impl FnOnce(Depth) -> Depth) -> Self::Target {
use XirfToken::*;