migrate the book
This commit is contained in:
parent
01e968ddd8
commit
ec6b0dcf5a
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
book
|
16
book.toml
Normal file
16
book.toml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
[book]
|
||||||
|
authors = ["Alisa Feistel"]
|
||||||
|
language = "en"
|
||||||
|
multilingual = false
|
||||||
|
src = "src"
|
||||||
|
title = "Monads in Rust"
|
||||||
|
|
||||||
|
[build]
|
||||||
|
build-dir = "book"
|
||||||
|
create-missing = false
|
||||||
|
|
||||||
|
[output.html]
|
||||||
|
default-theme = "navy"
|
||||||
|
mathjax-support = true
|
||||||
|
git-repository-url = "https://gitea.parrrate.ru/PTV/radn-rs"
|
||||||
|
edit-url-template = "https://gitea.parrrate.ru/PTV/radn-rs/_edit/main/book/{path}"
|
12
src/SUMMARY.md
Normal file
12
src/SUMMARY.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Summary
|
||||||
|
|
||||||
|
[Introduction](./ch00/s00-introduction.md)
|
||||||
|
|
||||||
|
- [Background](./ch01/s00-background.md)
|
||||||
|
- [Implementation](./ch02/s00-implementation.md)
|
||||||
|
- [Usage]()
|
||||||
|
- [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)
|
1
src/ch00/s00-introduction.md
Normal file
1
src/ch00/s00-introduction.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Introduction
|
1
src/ch01/s00-background.md
Normal file
1
src/ch01/s00-background.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Background
|
1
src/ch02/s00-implementation.md
Normal file
1
src/ch02/s00-implementation.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Implementation
|
19
src/ch04/s00-concerns.md
Normal file
19
src/ch04/s00-concerns.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# 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?
|
97
src/ch04/s01-alternatives.md
Normal file
97
src/ch04/s01-alternatives.md
Normal 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)
|
||||||
|
}
|
||||||
|
```
|
18
src/ch04/s02-lifetimes.md
Normal file
18
src/ch04/s02-lifetimes.md
Normal 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;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
5
src/ch04/s03-stackless.md
Normal file
5
src/ch04/s03-stackless.md
Normal 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.
|
5
src/ch04/s04-covariance.md
Normal file
5
src/ch04/s04-covariance.md
Normal 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)
|
Loading…
Reference in New Issue
Block a user