Last active
June 24, 2022 22:13
-
-
Save hyphenrf/f1743f49590321f6701c041aafb19512 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Today it was asked on discord whether Haskell's typeclasses and Rust's traits are equivalent. | |
The answer came from a Haskeller that: | |
> Yes, they’re along the same lines. | |
> Haskell’s typeclasses are more powerful than Rust’s traits though | |
I found that claim a little dubious so I asked them to elaborate.. How are traits less powerful? | |
To which a friend of mine suggested, maybe because Rust doesn't offer functional dependencies. | |
I didn't see why they can't be emulated with existent features. So I replied with that, | |
and repeated that I don't think a system is more powerful than the other, | |
although admitting that Haskell provides the features in a more ergonomic way. | |
One of the members challenged my claim: | |
> how would you simulate something like `class FunDep a b | a -> b, b -> a`? | |
So.. here's how :P | |
*/ | |
trait Depends { type On; } // `A : Depends<On=B>` in Rust == `b -> a` in Haskell | |
trait FunDep<B : Depends<On=Self>> : Depends<On=B> { } | |
// instance FunDep I32 F32 | |
impl FunDep<f32> for i32 {} | |
impl Depends for f32 { type On = i32; } | |
impl Depends for i32 { type On = f32; } | |
// now let's try some erroneous instances to make sure we're correct | |
// instance FunDep I32 F64 -- error! I32 is already used | |
// instance FunDep I64 F32 -- error! F32 is already used | |
impl Depends for f64 { type On = i32; } // ok | |
impl Depends for i64 { type On = f32; } // ok | |
/* | |
// error 1 | |
impl FunDep<f64> for i32 {} // error, mismatch between f64 and f32 | |
// this happens during typechecking the impl, resolving the `Depends for i32` impl. | |
impl Depends for i32 { type On = f64; } // error, conflicting implementations | |
*/ | |
/* | |
// error 2, same idea but swapping positions of the offending type | |
impl FunDep<f32> for i64 {} | |
impl Depends for f32 { type On = i64; } | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment