6 ms·
This is also how interfaces are implemented in Go.
by rwj 11y ago
This is also how interfaces are implemented in Go.
- nostrademons 11y agoAnd typeclasses in Haskell as well.
- evanpw 11y agoI don't think that's true. Dictionary-passing (or something equivalent) attaches the table of methods to the functions which take typeclass instances as arguments (with extra, hidden arguments), while Rust's Box<Trait> attaches the table of methods to the object pointer itself. So you can have a list of Box<Show> in Rust, but you can't have a list of Show in Haskell. You have to set up the extra indirection yourself using something like this: https://wiki.haskell.org/Existential_type#Dynamic_dispatch_mechanism_of_OOP https://wiki.haskell.org/Existential_type#Dynamic_dispatch_m.... I'm not an expert in Rust or Haskell, though, so I welcome corrections.
- bodhi 11y ago> but you can't have a list of Show in Haskell I'm not sure exactly what you mean, but my naive interpretation is that you can: Prelude> :t map show map show :: Show a => [a] -> [String]
- dbaupp 11y agoI'm not exactly sure what they mean, since the following works, and is pretty much a drop-in replacement for a Box<...> trait object in Rust. data Showable = forall a. Show a => Showable a This allows for [Showable 1, Showable "foo", Showable 'x'] (It requires the ExistentialQuantification language feature.)
- evanpw 11y agoRight, this is exactly what I meant by setting up the indirection yourself. The main difference seems to be that in Haskell, you have to write this code separately for each typeclass, and wrap/unwrap it manually. In Rust, you just change Show to &Show and you get dynamic dispatch with no extra code. Here's a gist of the two approaches: https://gist.github.com/evanpw/89d89aae1159c608c476 https://gist.github.com/evanpw/89d89aae1159c608c476. One other difference is that in the Haskell showStatic, static dispatch is not a guarantee, just an optimization.
- bodhi 11y agoThis works on single instances, but I'm trying to see how it plays out with lists of `Bar`. As far as I can see, you need to use `Box`: https://play.rust-lang.org/?code=struct%20Foo%3B%0Astruct%20Baz%3B%0A%20%0Atrait%20Bar%20%7B%0A%20%20%20%20fn%20baz(%26self)%20-%3E%20i64%3B%0A%7D%0A%20%0Aimpl%20Bar%20for%20Foo%20%7B%0A%20%20%20%20fn%20baz(%26self)%20-%3E%20i64%20%7B%2010%20%7D%0A%7D%0A%0Aimpl%20Bar%20for%20Baz%20%7B%0A%20%20%20%20fn%20baz(%26self)%20-%3E%20i64%20%7B%2020%20%7D%0A%7D%0A%20%0Afn%20show_static%3CT%3A%20Bar%3E(t%3A%20%26T)%20-%3E%20String%20%7B%0A%20%20%20%20t.baz().to_string()%0A%7D%0A%20%0Afn%20show_dynamic(t%3A%20%26Bar)%20-%3E%20String%20%7B%0A%20%20%20%20t.baz().to_string()%0A%7D%0A%20%0Afn%20main()%20%7B%0A%20%20%20%20let%20foo%20%3D%20Foo%3B%0A%20%20%20%20let%20baz%20%3D%20Baz%3B%0A%20%20%20%20let%20k%3A%5BBox%3C%26Bar%3E%3B%202%5D%20%3D%20%5BBox%3A%3Anew(%26foo)%2C%20Box%3A%3Anew(%26baz)%5D%3B%0A%20%20%20%20println!(%22%7B%7D%20%7B%7D%22%2C%20show_static(%26foo)%2C%20show_dynamic(%26foo))%3B%0A%7D&version=beta https://play.rust-lang.org/?code=struct%20Foo%3B%0Astruct%20... Which seems to me to be effectively the same as `Barrable` in this case, although it's more generic.
- bodhi 11y ago> As far as I can see, you need to use `Box` Which is exactly what you said in the first place! > So you can have a list of Box<Show> in Rust, but you can't have a list of Show in Haskell. But isn't this comparing two different things? You can't have a list of trait/typeclass in either language (excuse the pseudo-syntax): Rust: [Bar] Haskell: [Bar a => a] But you can (with some extensions in Haskell) have: Rust: [Box<Bar>] Haskell: [Box Bar]
- twic 11y agoThat takes a list of a, where a is some type which is Show. You can't have a grab-bag of different Show things in there.
- kimundi 11y agoThat's not a list of Show, that's a list of a single type that instantiates Show. The difference being that in your code you can only put in a single type at a time, eg [Int] or [String], but not both Int and String under the common Show interface type.
- bodhi 11y agoAha, thanks (to twic also). Now I get it!