Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't Unify Super Generic Code #31580

Open
Gankro opened this Issue Feb 11, 2016 · 5 comments

Comments

Projects
None yet
5 participants
@Gankro
Copy link
Contributor

Gankro commented Feb 11, 2016

I was trying to verify that the associated-items-based HKT described in the associated items RFC still worked. As best I know, I updated everything to work with today's stable Rust (1.7), but it fails out in unifying in the actual implementation of Mappable for Vec<T> (see the FIXME).

// The kind * -> *
trait TypeToType<Input> {
    type Output;
}

struct Vec_;

impl<T> TypeToType<T> for Vec_ {
    type Output = Vec<T>;
}

trait Mappable 
    where Self: Sized,
{
    type E;
    type HKT: TypeToType<Self::E, Output=Self>;

    fn map<F, O>(self, f: F) -> <Self::HKT as TypeToType<O>>::Output
        where F: FnMut(Self::E) -> O,
              Self::HKT: TypeToType<O>;
}

impl<T> Mappable for Vec<T> {
    type E = T;
    type HKT = Vec_;

    // FIXME: I won't unify `Vec_::Output = Vec<O>`!
    fn map<F, O>(self, mut f: F) -> <Self::HKT as TypeToType<O>>::Output
        where F: FnMut(Self::E) -> O,
              Self::HKT: TypeToType<O>
    {
        let r: Vec<O> = self.into_iter().map(&mut f).collect();
        r
    }

}


fn main() {
    let nums: Vec<u32> = vec![1, 2, 3, 4, 5, 6];
    let bools: Vec<bool> = nums.map(|x| x < 3);
}
@aturon

This comment has been minimized.

Copy link
Member

aturon commented Feb 11, 2016

@jonas-schievink

This comment has been minimized.

Copy link
Member

jonas-schievink commented Feb 11, 2016

cc #30472 and #28994 (dupe?)

@aturon

This comment has been minimized.

Copy link
Member

aturon commented Feb 11, 2016

@jonas-schievink Yes, I think you're right -- the projection works if you define a helper like:

fn project<O>(v: Vec<O>) -> <Vec_ as TypeToType<O>>::Output {
    v
}

@aturon aturon closed this Feb 11, 2016

@aturon

This comment has been minimized.

Copy link
Member

aturon commented Feb 11, 2016

Actually, I was a bit too hasty: HRTBs are not clearly at fault here, since there's no lifetime involved in the FnMut where clause. I suspect it's related, but not identical to the other bugs.

@aturon aturon reopened this Feb 11, 2016

@Gankro

This comment has been minimized.

Copy link
Contributor Author

Gankro commented Feb 11, 2016

The full fix, to be clear:

fn project_vec<O>(v: Vec<O>) -> <Vec_ as TypeToType<O>>::Output {
    v
}

impl<T> Mappable for Vec<T> {
    type E = T;
    type HKT = Vec_;

    fn map<F, O>(self, mut f: F) -> <Self::HKT as TypeToType<O>>::Output
        where F: FnMut(Self::E) -> O,
              Self::HKT: TypeToType<O>
    {
        let r: Vec<O> = self.into_iter().map(&mut f).collect();
        project_vec::<O>(r)
    }

}

But this shouldn't be necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.