What is the difference between traits in Rust and typeclasses in Haskell?

前端 未结 3 891
旧时难觅i
旧时难觅i 2020-12-12 12:15

Traits in Rust seem at least superficially similar to typeclasses in Haskell, however I\'ve seen people write that there are some differences between them. I was wondering e

3条回答
  •  误落风尘
    2020-12-12 12:53

    I think the current answers overlook the most fundamental differences between Rust traits and Haskell type classes. These differences have to do with the way traits are related to object oriented language constructs. For information about this, see the Rust book.

    1. A trait declaration creates a trait type. This means that you can declare variables of such a type (or rather, references of the type). You can also use trait types as parameters on function, struct fields and type parameter instantiations.

      A trait reference variable can at runtime contain objects of different types, as long as the runtime type of the referenced object implements the trait.

      // The shape variable might contain a Square or a Circle, 
      // we don't know until runtime
      let shape: &Shape = get_unknown_shape();
      
      // Might contain different kinds of shapes at the same time
      let shapes: Vec<&Shape> = get_shapes();
      

      This is not how type classes work. Type classes create no types, so you can't declare variables with the class name. Type classes act as bounds on type parameters, but the type parameters must be instantiated with a concrete type, not the type class itself.

      You can not have a list of different things of different types which implement the same type class. (Instead, existential types are used in Haskell to express a similar thing.) Note 1

    2. Trait methods can be dynamically dispatched. This is strongly related to the things that are described in the section above.

      Dynamic dispatch means that the runtime type of the object a reference points is used to determine which method that is called though the reference.

      let shape: &Shape = get_unknown_shape();
      
      // This calls a method, which might be Square.area or
      // Circle.area depending on the runtime type of shape
      print!("Area: {}", shape.area());
      

      Again, existential types are used for this in Haskell.

    In Conclusion

    It seems to me like traits are in many aspects the same concept as type classes. It addition, they have the functionality of object oriented interfaces.

    On the other hand Haskell's type classes are more advanced. Haskell has for example higher-kinded types and extension like multi-parameter type classes.


    Note 1: Recent versions of Rust have an update to differentiate the usage of trait names as types and the usage of trait names as bounds. In a trait type the name is prefixed by the dyn keyword. See for example this answer for more information.

提交回复
热议问题