ch04 reorg

This commit is contained in:
AF 2023-05-02 00:49:23 +00:00
parent 509ffacd4c
commit 21e4496201
8 changed files with 158 additions and 30 deletions

13
.vscode/settings.json vendored
View File

@ -1,3 +1,14 @@
{ {
"rust-analyzer.showUnlinkedFileNotification": false "rust-analyzer.showUnlinkedFileNotification": false,
"[rust]": {
"editor.rulers": [
100
]
},
"[markdown]": {
"editor.rulers": [
99,
100
]
}
} }

View File

@ -6,6 +6,7 @@ src = "src"
title = "Monads in Rust" title = "Monads in Rust"
[build] [build]
build-dir = "book"
create-missing = false create-missing = false
[output.html] [output.html]

View File

@ -6,3 +6,7 @@
- [Implementation](./ch02/s00-implementation.md) - [Implementation](./ch02/s00-implementation.md)
- [Usage]() - [Usage]()
- [Current Implementation Concerns](./ch04/s00-concerns.md) - [Current Implementation Concerns](./ch04/s00-concerns.md)
- [Alternative Monad Traits](./ch04/s01-alternatives.md)
- [Lifetimes](./ch04/s02-lifetimes.md)
- [Stackless](./ch04/s03-stackless.md)
- [Covariance](./ch04/s04-covariance.md)

View File

@ -1,32 +1,19 @@
# Concerns (questions) with the current implementaion # Concerns (questions) with the current implementaion
## There exist alternative `Functor` implementations
See the [relevant subchapter](s01-alternatives.md)
## It might be better to have a per-lifetime trait for `Functor`s
See the [relevant subchapter](s02-lifetimes.md)
## `Stackless` is kind of bad
See the [relevant subchapter](s03-stackless.md)
## `WeakFunctor::F<'a, A>` is not (yet) covariant over the lifetime `'a`
See the [relevant subchapter](s04-covariance.md)
## Can `WeakFunctor` be an associated type of a `Functor` instead of its supertype? ## Can `WeakFunctor` be an associated type of a `Functor` instead of its supertype?
## `Clone`-`FnMut` category functors
## `Copy`-`Fn` category functors
## `WeakFunctor::F<'a, A>` is not (yet) covariant over the lifetime `'a`.
### Specific case: `Stackless<'a>` isn't covariant.
Current hypothesis is that this comes from `EvalTree<'a>` being invariant over `'a`
due to `FnOnce` being invariant over its output,
which in turn comes from present typesysten limitations.
## It might be better to have a per-lifetime trait for `Functor`s.
Current:
```rust
pub trait WeakFunctor {
type F<'a, A: 'a>: 'a
where
Self: 'a;
}
```
Proposed:
```rust
pub trait WeakFunctor<'a>: 'a {
type F<A: 'a>: 'a;
}
```

View File

@ -0,0 +1,97 @@
# Atlernatives to `Functor` trait
## `_`-`FnOnce` category functors (current)
Copied for reference. All following examples are in the same `Functor`-`Applicative`-`Monad` format
without extra (sub)traits like `WeakFunctor`, `Pure`, `ApplicativeLA2`, etc. .
```rust
trait Functor {
type F<'a, A: 'a>: 'a
where
Self: 'a;
fn fmap<'a, A: 'a, B: 'a>(
f: impl 'a + FnOnce(A) -> B, fa: Self::F<'a, A>,
) -> Self::F<'a, B>
where
Self: 'a;
}
fn fmap<'a, T: 'a + Functor, A: 'a, B: 'a>(
f: impl 'a + FnOnce(A) -> B,
) -> impl FnOnce(T::F<'a, A>) -> T::F<'a, B> {
|fa| T::fmap(f, fa)
}
```
## `Clone`-`Fn` category functors
This is probably the closest representation to what Haskell views as a category of its types.
```rust
trait Functor: Clone {
type F<'a, A: 'a + Clone>: 'a + Clone
where
Self: 'a;
fn fmap<'a, A: 'a + Clone, B: 'a + Clone>(
f: impl 'a + Clone + Fn(A) -> B, fa: Self::F<'a, A>,
) -> Self::F<'a, B>
where
Self: 'a;
}
fn fmap<'a, T: 'a + Functor, A: 'a + Clone, B: 'a + Clone>(
f: impl 'a + Clone + Fn(A) -> B,
) -> impl 'a + Clone + Fn(T::F<'a, A>) -> T::F<'a, B> {
move |fa| T::fmap(f.clone(), fa)
}
```
## `Clone`-`FnMut` category functors
We view use of `FnMut` for category's morphisms as somewhat controversial[^e].
* Use of direct/indirect mutable references is, arguably, counter-functional[^e].
* `Clone+FnMut` is, generally, nonsensical[^e].
* Due to that, morphisms category isn't a subcategory, so can't be wrapped.
* Not being to wrap morphisms makes implementation of one specific `Applicative` method,
sequential application (`<*>` in Haskell, `seq` in RADN) *difficult*.
```rust
trait Functor: Clone {
type F<'a, A: 'a + Clone>: 'a + Clone
where
Self: 'a;
fn fmap<'a, A: 'a + Clone, B: 'a + Clone>(
f: impl 'a + FnMut(A) -> B, fa: Self::F<'a, A>,
) -> Self::F<'a, B>
where
Self: 'a;
}
```
[^e]: elaborate?
## `Copy`-`Fn` category functors
```rust
trait Functor: Copy {
type F<'a, A: 'a + Copy>: 'a + Copy
where
Self: 'a;
fn fmap<'a, A: 'a + Copy, B: 'a + Copy>(
f: impl 'a + Copy + Fn(A) -> B, fa: Self::F<'a, A>,
) -> Self::F<'a, B>
where
Self: 'a;
}
fn fmap<'a, T: 'a + Functor, A: 'a + Copy, B: 'a + Copy>(
f: impl 'a + Copy + Fn(A) -> B,
) -> impl 'a + Copy + Fn(T::F<'a, A>) -> T::F<'a, B> {
move |fa| T::fmap(f, fa)
}
```

View File

@ -0,0 +1,18 @@
# Making lifetimes a parameter of a trait instead of that of the GAT
Current:
```rust
pub trait WeakFunctor {
type F<'a, A: 'a>: 'a
where
Self: 'a;
}
```
Proposed:
```rust
pub trait WeakFunctor<'a>: 'a {
type F<A: 'a>: 'a;
}
```

View File

@ -0,0 +1,5 @@
# `Stackless<'a>` isn't covariant
Current hypothesis is that this comes from `EvalTree<'a>` being invariant over `'a`
due to `FnOnce` being invariant over its output,
which in turn comes from present typesysten limitations.

View File

@ -0,0 +1,5 @@
## `CovariantFunctor` not (yet) included in `Monad`
## Specific case: `Stackless<'a>` isn't covariant
See the [relevant subchapter](s03-stackless.md)