返回

泛型.带GATs的functor/monad实现

发布时间:2022-09-07 17:36:01 425
# html# rust# git# github# 脚本

目前,我试图在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);

请告知。

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像