泛型.带GATs的functor/monad实现
目前,我试图在Rust中实现一个函子/单子。
基本上,在我自己的项目中,我很乐意在Haskell/Typescript和Rust之间共享相同的概念和类似的代码库设计。
例如,我更喜欢从一个非常基本的函子/单子开始,它只是函数应用程序的一个二进制操作,即f(x)
.
在哈斯克尔,
pipe :: (a -> b) -> a -> b
pipe = \f -> \a -> f a
然后
--(|>) = flip ($) / (&)
(|>) :: a -> (a -> b) -> b
(|>) = flip pipe
infixl 1 |>
我喜欢原始代码的简单性,实际上我想自己声明它。|>
通常被称为;管道操作员“;用F#或其他FP语言。
事实上|>
是一个单子运算符,可以满足所谓的单子定律,这段代码的优点是只需替换pipe
对另一个foo
,我们可以定义另一个函子/单子操作。
因此,相应地,相似性也适用于类型脚本代码。
type pipe =
(f: (a: A) => B) => (a: A) => B;
const pipe: pipe = f => a => f(a);
然后
//extend Object.prototype with pipe operator as 'map'
const map = Symbol("for pipe");
Object.assign(
Object.prototype,
{
[map]: function (
this: A,
f: (a: A) => B) { return pipe(f)(this); }
}
);
请注意,我是通过扩展Object.prototype
(JS中的反模式)只是为了演示如何实现pipe
.
这一点在JS中也很重要,可以重复使用简明的pipe
定义并将其替换为其他函数,创建其他函子/单子将很容易。因此,我很乐意使用这种设计模式,在Haskell和Typescript之间切换相同的概念。
这是主要部分。理想情况下,我想在Rust代码中重复相同的设计模式。对我来说,这是一种舒适、集成和高效的方法,更容易向他人解释我的代码的概念。
我已经做了一个多月了,但因为我没有生锈的经验,所以没有真正成功。我反复阅读了很多声明,但在设计上有很多限制,我对此非常理解。我想做的是最好的拍摄模式,至少能够使用pipe
函数到函子/单子特征。
到目前为止,我正在学习下面的两个代码;
1:https://docs.rs/apply/0.3.0/apply/trait.Apply.html
/// Represents a type which can have functions applied to it (implemented
/// by default for all types).
pub trait Pipe {
/// Apply a function which takes the parameter by value.
fn pipe(self, f: F) -> B
where
Self: Sized,
F: FnOnce(Self) -> B,
{
f(self)
}
/// Apply a function which takes the parameter by reference.
fn pipe_ref(&self, f: F) -> B
where
F: FnOnce(&Self) -> B,
{
f(self)
}
/// Apply a function which takes the parameter by mutable reference.
fn pipe_mut(&mut self, f: F) -> B
where
F: FnOnce(&mut Self) -> B,
{
f(self)
}
}
impl Pipe for T {}
我已将值的名称从https://docs.rs/apply/0.3.0/src/apply/lib.rs.html
该代码的工作原理如下foo.pipe(f)
.
这里我想要一个函数,它的类型是:
type Pipe = dyn FnOnce(fn(A) -> B) -> dyn FnOnce(fn(A)-> B);
被替换为其他一元函数,
type FooMonad = dyn FnOnce(fn(A) -> M) -> dyn FnOnce(fn(A)-> M);
由于通用闭包和HKT的原因,两者都很难实现,但一旦有可能,我可以将其重写为
pub trait Pipe {
/// Apply a function which takes the parameter by value.
fn pipe(self, f: F) -> B
where
Self: Sized,
F: FnOnce(Self) -> B,
{
pipe(f)(self)
}
//.....
}
2:服贸总协定
HKT的工作代码可能是,夜间功能GATs:https://blog.rust-lang.org/2021/08/03/GATs-stabilization-push.html
我发现有希望的实现是:
https://github.com/RustyYato/type-families/blob/main/src/gat.rs
#![feature(generic_associated_types)]
pub trait Family: Copy {
type This; //<-- GATs
}
pub trait Functor: Family {
fn map B>(self, this: Self::This, f: F) -> Self::This;
}
抱歉花了这么长时间但我的问题是,
有没有可能在GATs中利用上述函子特性来实现T
(没有struct
)因为pipe
?
还有,我想写pipe
在Rust中独立运行,如在Typescript/Haskell中。
type pipe =
(f: (a: A) => B) => (a: A) => B;
const pipe: pipe = f => a => f(a);
请告知。