是否有内在的原因可以解释为什么Rust没有更高种类的类型?

abi*_*bol 5 monads traits functor higher-kinded-types rust

Rust没有更高种类的类型。例如,函子(以及因此的monad)不能用Rust编写。我想知道是否有深层原因对此进行解释以及原因。

例如,我能理解的原因可能是没有零成本的抽象使HKT成为可能。否则类型推论要困难得多。当然,我也正在寻找一种解释,向我说明为什么这是真正的限制。

如果答案已经在其他地方了,您可以给我链接吗?

Mat*_* M. 9

时间和优先权

本质上,缺少高级类型不是设计决定。Rust打算采用某种形式,目前最受欢迎的候选对象是Generic Associated Types(2017)

但是,实现这些功能需要花费时间,与其他功能相比,还没有被优先考虑。例如,异步/等待优先于HKT,而const泛型似乎也优先。


例如,函子(以及因此的monad)不能用Rust编写。

实际上,它们可以,尽管有点笨拙。

请参阅他在https://www.reddit.com/r/rust/comments/cajn09/new_method_for_emulating_higherkinded_types_in/上发布的Edmund Smith可爱的hack

trait Unplug {
    type F; //The representation type of the higher-kinded type
    type A; //The parameter type
}

trait Plug<A> {
    type result_t;
}

pub  struct  Concrete<M: Unplug + Plug<A>,A> {
    pub unwrap: <M as Plug<A>>::result_t
}

impl<M: Unplug + Plug<A>, A> Concrete<M,A> {
    fn of<MA: Unplug<F=M, A=A> + Plug<A>>(x: MA) -> Self
        where M: Plug<A, result_t = MA>
    {
        Concrete { unwrap: x }
    }
}
Run Code Online (Sandbox Code Playgroud)

他们实现了一个Functor特质:

pub trait Functor: Unplug + Plug<<Self as Unplug>::A> {
    fn map<B, F>(f: F, s: Self) -> <Self as Plug<B>>::result_t
        where
            Self: Plug<B>,
            F: FnMut(<Self as Unplug>::A) -> B
        ;
}

//  Example impl for a represented Vec
impl<A> Functor for Concrete<Vec<forall_t>, A> {
    //  remember, Self ~ (Vec<_>, A) ~ "f a"
    fn map<B, F>(f: F, s: Self) -> <Self as Plug<B>>::result_t
        where
            F: FnMut(<Self as Unplug>::A) -> B 
    {        
        Concrete::of(s.unwrap.into_iter().map(f).collect())
    }
}
Run Code Online (Sandbox Code Playgroud)

然后从构建ApplicativeMonad

pub trait Applicative: Functor {
    fn pure(s: <Self as Unplug>::A) -> Self;

    fn app<B, F>(
        f: <Self as Plug<F>>::result_t, //M<F>
        s: Self                         //M<A>
    ) -> <Self as Plug<B>>::result_t   //M<B>
    where
        F: FnMut(<Self as Unplug>::A) -> B + Clone,
        Self: Plug<F> + Plug<B> + Unplug,
        <Self as Plug<F>>::result_t:
            Unplug<F=<Self as Unplug>::F, A=F> +
            Plug<F> +
            Clone,
        <Self as Unplug>::F: Plug<F>
    ;
}

pub trait Monad : Applicative {
    fn bind<F,B>(f: F, s: Self) -> <Self as Plug<B>>::result_t
    where
        Self: Plug<F>+Plug<B>,
        F: FnMut(<Self as Unplug>::A) ->
            <Self as Plug<B>>::result_t + Clone
        ;
}
Run Code Online (Sandbox Code Playgroud)

我确实说这有点笨拙...

  • @abitbol我认为你错过了你不能“仅仅”将类似Haskell的HKT添加到Rust中——你需要(1)定义该功能如何与语言的其余部分交互以及(2)实际实现它。GAT 是一个小的、正交的特征,已经被完全定义并正在实施。[本博客系列](http://smallcultfollowing.com/babysteps/blog/2016/11/02/linked-type-constructors-part-1-basic-concepts-and-introduction/)(分 4 部分)描述详细说明了 GAT(当时称为 ATC)和 HKT 之间的关系。 (2认同)