HackerTrans
TopNewTrendsCommentsPastAskShowJobs

_answ

no profile record

comments

_answ
·2 years ago·discuss
A list is a monad, but not because it wraps another type. What you're describing is higher kinded types.

A monad is a specific variant of a higher kinded type whose primary property lies in the fact that its value can be "evolved" via a specific function application (usually known as the "bind" operation). This sounds confusing but it's really a simple concept: if you take a higher kinded type, you can think about the values within it as the data and the type itself as metadata or a context of some sort. For example, an int is a piece of data, but a `Maybe int` is the same data with the added context of it being possibly absent.

A monad is not the only higher kinded type. Probably the most familiar HKT to working programmers (even if they don't know it) is the functor, which is a type that can be mapped over (in the sense of map-filter-reduce). If you have a `Foo<A>`, you can apply a function to turn it into a `Foo<B>`. However, a limitation of the functor is that you can only affect the data at the individual item level, not the context as a whole, so if you put a list of five values in, you'll get a list of five values back.

If we want to affect the context as well, we instead need a type like the monad, where we can "bind" a function that takes the inner value and returns a whole new wrapper based on it.

Why is this useful? Well, it can express a lot of different things very neatly - for example, fallible computation. Let's say you have two functions that both return a Maybe monad. In a language with nulls, you'd likely have to do something like `a = foo(); if (a is null) return; b = bar(); if (b is null) return`, which is tedious and error prone. Monads lend themselves to composing such chains extremely well, so you can simply do `foo().and_then(_ => bar())` and in the end have a value that combines the result (success or failure) of both of those functions.

Null values = chains of null checks = monads! Futures = chains of callbacks = monads! Mutable state = chains of writes = monads! Sequential execution = chains of statements = monads! And so on and so forth. You can get pretty crazy with it, not that I would recommend it.

Monads seem complicated and scary because most mainstream programming languages don't have the necessary abstractions to talk about higher kinded types as its own thing, but in reality most programmers are using monads daily without even realizing.
_answ
·2 years ago·discuss
Simple != idiomatic. It's perfectly idiomatic to `Arc<Mutex<Box>>` in Rust, and it is more complex because it deals with more concerns than a simple reference, namely being thread-safe. Sometimes you need that, sometimes not, but you have to be explicit about it.
_answ
·2 years ago·discuss
I have a feeling that most of the clarity you find in your example comes from better use of whitespace. Consider:

    pub fn read<P>(path: P) -> io::Result<Vec<u8>>
    where
        P: AsRef<Path>,
    {
        fn inner(path: &Path) -> io::Result<Vec<u8>> {
            let mut bytes = Vec::new();
    
            let mut file = File::open(path)?;
            file.read_to_end(&mut bytes)?;
    
            Ok(bytes)
        }
    
        inner(path.as_ref())
    }
Plus, your example does not have the same semantics as the Rust code. You omitted generics entirely, so it would be ambiguous if you want monomorphization or dynamic dispatch. Your `bytes` and `file` variables aren't declared mutable. The `try` operator is suddenly a statement, which precludes things like `foo()?.bar()?.baz()?` (somewhat normal with `Option`/`Error`). And you weirdly turned a perfectly clear `&mut` into a cryptic `&!`.

Please don't assume that the syntax of Rust has been given no thought.
_answ
·2 years ago·discuss
The lossy vs lossless distinction loses its meaning in the absence of provenance. You can compress a bitmap into a .jpg q=1, and then save it as a .png. The .png is technically lossless, but that clearly doesn't tell much about the image quality. Conversely, many cameras shoot JPEG as the source format. The .jpg is, in effect, the master copy from which the loss is measured (obviously there are losses from the sensor data, but still).
_answ
·2 years ago·discuss
Speaking from the experience of building small web apps for personal use, trying to follow semantic HTML in good faith has been nothing but a source of frustration. The rules are clearly molded around static, primarily text-based documents defined upfront, and anything that doesn't fit this format feels like a second citizen at best. Take headings, for example: in component-based development, I often don't know (and shouldn't care) what level a heading is in my reusable widget, but I am forced to choose regardless. As much as I want to be a good citizen, if I have to fight the platform for it, you're getting divs and h2's everywhere.