Is there an intrinsic reason explaining why Rust does not have higher-kinded-types?

前端 未结 1 2001
遇见更好的自我
遇见更好的自我 2021-02-14 04:48

Rust does not have higher-kinded-types. For example, functor (and thus monad) cannot be written in Rust. I would like to know if there is a deep reason explaining this and why.<

相关标签:
1条回答
  • 2021-02-14 05:05

    Time & Priority.

    The absence of Higher Kinded Types is not a design decision, per se. It is intended that Rust will have some form of it, with the more popular candidate being Generic Associated Types (2017) at the moment.

    Implementing those take time, though, and has not been judged a priority compared to other features. For example, async/await was prioritized over HKTs, and const generics also seem to be prioritized.


    For example, functor (and thus monad) cannot be written in Rust.

    Actually, they can, although it's a bit unwieldy.

    See Edmund's Smith lovely hack which he posted on https://www.reddit.com/r/rust/comments/cajn09/new_method_for_emulating_higherkinded_types_in/:

    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 }
        }
    }
    

    With which they implement a Functor trait:

    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())
        }
    }
    

    And from then on build Applicative and Monad:

    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
            ;
    }
    

    I did say it was a bit unwieldy...

    0 讨论(0)
提交回复
热议问题