If we were to create a Rust version of this page for Haskell, what cool programming techniques would you add to it?

  • tatterdemalion@programming.dev
    link
    fedilink
    arrow-up
    3
    arrow-down
    1
    ·
    3 hours ago

    One thing I like a lot about Rust is that it rarely does blow my mind.

    But one crate that actually did blow my mind is corosensei. It’s not Rust per se that is so crazy here, but the way it’s essentially implementing a new language feature with assembly code. This is how you know Rust really is a systems programming language. I invite you to read the source code.

  • Infernaltoast@programming.dev
    link
    fedilink
    arrow-up
    3
    ·
    edit-2
    3 hours ago

    You can manually implement PartialEq and Eq on an Enum that implements Hash to manually determine how the hashmap keys override/collide with one another.

  • tuna@discuss.tchncs.de
    link
    fedilink
    arrow-up
    9
    ·
    7 hours ago

    Something i didnt know for a long time (even though its mentioned in the book pretty sure) is that enum discriminants work like functions

    #[derive(Debug, PartialEq, Eq)]
    enum Foo {
        Bar(i32),
    }
    
    let x: Vec<_> = [1, 2, 3]
        .into_iter()
        .map(Foo::Bar)
        .collect();
    assert_eq!(
        x,
        vec![Foo::Bar(1), Foo::Bar(2), Foo::Bar(3)]
    );
    

    Not too crazy but its something that blew my mind when i first saw it

    • Ephera@lemmy.ml
      link
      fedilink
      arrow-up
      7
      ·
      7 hours ago

      This works with anything that one might call “named tuples”.

      So, you can also define a struct like so and it’ll work:

      struct Baz(i32);
      

      On the other hand, if you define an enum variant with the normal struct syntax, it does not work:

      enum Foo {
          ...
          Qux { something: i32 } //cannot omit braces
      }
      
      • barsoap
        link
        fedilink
        arrow-up
        1
        ·
        edit-2
        5 hours ago

        Named function arguments would occasionally be nice to have instead of the single n-tuple they take now. Currently I’m more or less playing a game of "can I name my local variables such that rust-analyzer won’t display the argument name when I stick them into functions (because they’re called the same)).

        • Ephera@lemmy.ml
          link
          fedilink
          arrow-up
          1
          ·
          3 hours ago

          Yeah, I do miss those, too, although I’ve noticed that I’m becoming ever more consistent with just naming my variables like the type is called and that works out nicely in Rust, because then you can also leave out the field name when filling in a struct with named fields. I’ll often have named my function parameters the same name that I ultimately need to pass into structs fields.

          At this point, I’m secretly wondering, if a programming language could be designed where you don’t normally fill in variable names, but rather just use the type name to reference each value.
          For the few cases where you actually do have multiple variables of the same type, then you could introduce a local (type) alias, much like it’s currently optional to add type annotations.
          Someone should build this, so I don’t have to take on another side project. 🙃

      • barsoap
        link
        fedilink
        arrow-up
        2
        ·
        5 hours ago

        Enum constructors are functions, this typechecks:

        fn foo<T>() {
            let f: fn(T) -> Option<T> = Some;
        }
        

        I was a bit apprehensive because rust has like a gazillion different function types but here it seems to work like just any other language with a HM type system.

    • barsoap
      link
      fedilink
      arrow-up
      2
      ·
      3 hours ago

      That makes complete sense. Ranges implement fmt::Debug, .. is a range, in particular the full range (all values) ..= isn’t because the upper bound is missing but ..=.. ranges from the beginning to the… full range. Which doesn’t make sense semantically but you can debug print it so add a couple more nested calls and you get a punch card.

      I totally didn’t need the Rust playground to figure that out.

      • SorteKanin@feddit.dk
        link
        fedilink
        arrow-up
        15
        ·
        9 hours ago

        It’s a test for the compiler which ensures that these legal yet extremely weird expressions continue to compile as the compiler is updated. So there is a purpose to the madness but it does still look pretty funny.

  • Ephera@lemmy.ml
    link
    fedilink
    arrow-up
    14
    ·
    10 hours ago

    A cool thing you can do, is to store values of all kinds of types in a big HashMap, basically by storing their TypeId and casting them to Box<dyn Any> (see std::any).
    Then you can later retrieve those values by specifying the type (and optionally another ID for storing multiple values of the same type).

    So, you can create an API which is used like this:

    let value = MyType::new();
    storage.insert(value);
    let retrieved = storage.get::<MyType>();
    assert_eq!(retrieved, value);
    

    There’s various ECS storage libraries which also implement such an API. Depending on what you’re doing, you might prefer to use those rather than implementing it yourself, but it’s not too difficult to implement yourself.

  • silasmariner@programming.dev
    link
    fedilink
    arrow-up
    13
    ·
    14 hours ago

    Rust isn’t really a language that lends itself to terse point-free functional idioms… The sort of examples I might want to share would probably require a bit more context, certainly more code. Like I think type guards and arena allocation are cool and useful tricks but I don’t think I could write a neat little example showing or motivating either

  • solrize@lemmy.world
    link
    fedilink
    arrow-up
    4
    ·
    edit-2
    12 hours ago

    I’d like to see a Rust solution to Tony Morris’s tic tac toe challenge:

    https://blog.tmorris.net/posts/scala-exercise-with-types-and-abstraction/index.html

    His rant about it is here:

    https://blog.tmorris.net/posts/understanding-practical-api-design-static-typing-and-functional-programming/

    I did a Haskell GADT solution some time back and it’s supposed to be doable in Java and in C++. Probably Rust too. I wonder about Ada.

      • solrize@lemmy.world
        link
        fedilink
        arrow-up
        1
        ·
        4 minutes ago

        Neat that looks interesting. There’s a similar Haskell idiom called session types. I have a bit of reservation about whether one can easily use Rust traits to mark out the permissible state sets that an operation can take, but that’s because I don’t know Rust at all. I do remember doing a hacky thing with TypeLits in Haskell: basically you can have numbers in the type signatures and do some limited arithmetic with them at type level. I’d be interested to know if that is doable in Rust.

  • BB_C@programming.dev
    link
    fedilink
    arrow-up
    1
    arrow-down
    1
    ·
    edit-2
    8 hours ago

    Can’t think of anything.
    The novelty must have worn off over time.
    Or maybe my mind doesn’t get blown easily.