2

Trying to write something similar to Haskell's HList, with the ability to search by type. With the below code, in play.rust-lang.org version rustc 0.13.0-dev (567b90ff0 2014-12-13 20:02:15 +0000) I get an error:

<anon>:35:26: 35:31 error: unable to infer enough type information to locate the impl of the trait `ContainsRel<int, _>` for the type `HCons<int, HNil>`; type annotations required
<anon>:35     let foo: &int = list.get();
                                   ^~~~~

I'm not sure why it can't infer the proper type, HNil has no ContainsRel impls.

trait HList {}

struct HNil;
struct HCons<H, T: HList>(H, T);

impl HList for HNil {}
impl<H, T: HList> HList for HCons<H, T> {}


trait Peano {}

struct Zero;
struct Succ<N: Peano>(N);

impl Peano for Zero {}
impl<N: Peano> Peano for Succ<N> {}

trait ContainsRel<E, P: Peano> {
    fn get(&self) -> &E;
}

impl<E, L: HList> ContainsRel<E, Zero> for HCons<E, L> {
    fn get(&self) -> &E {
        &self.0
    }
}
impl<E, X, L: ContainsRel<E, P>+HList, P: Peano> ContainsRel<E, Succ<P>> for HCons<X, L> {
    fn get(&self) -> &E {
        self.1.get()
    }
}

fn main() {
    let list: HCons<uint, HCons<int, HNil>> = HCons(5u, HCons(6i, HNil));
    let foo: &int = list.get();
}
Sgeo
  • 85
  • 8
  • No one said that `HNil` has any `ContainsRel` impls; but `HCons` has a `ContainsRel` impl because `HNil` implements `HList`. – Chris Morgan Dec 15 '14 at 04:58
  • Right, but it should only have one `ContainsRel` impl, the `ContainsRel` one. So why is it ambiguous which `ContainsRel` impl to use? – Sgeo Dec 15 '14 at 05:04
  • Code similar to this is compiling now. – Sgeo Sep 27 '15 at 02:51

1 Answers1

3

Someone could impl the Peano trait for another type, even in another crate, and then the list.get() in main would become ambiguous. If you try to substitute types manually in the impl, you get:

impl <E=int, X=uint , L=HCons<int, HNil>, P=?> ContainsRel<int, Succ<P=?>> for HCons<uint, HCons<int,HNil>>

With the types defined so far, P must be Zero (as it's the only implementation of Peano in scope), but anyone would be allowed to define another struct that implements P in another module, so Rust forces you to be explicit. For instance, adding this would be valid:

struct Foo;
impl Peano for Foo {}
impl<E, L: HList> ContainsRel<E, Foo> for HCons<E, L> {
    fn get(&self) -> &E {
        &self.0
    }
}

Specifying the type of P works:

let foo: &int = ContainsRel::<_, Succ<Zero>>::get(&list);

...but yes, it does not look great.

Paolo Falabella
  • 24,914
  • 3
  • 72
  • 86
  • Is there anything coming up that will allow the sort of code I'm trying to write? Or do I just need a closed trait system? – Sgeo Dec 16 '14 at 03:54
  • I think the problem boils down to the fact that you need to tell the compiler what (index of the) value you're trying to access, because an HList could contain various elements with the same type. You could do something like this http://is.gd/FsZMGw . Macros could generate the various methods for you. – Paolo Falabella Dec 16 '14 at 13:19