[-] balsoft@lemmy.ml 1 points 9 hours ago

In a very technical way, they did. You won't see a product called "veggie burger" on the store shelves.

[-] balsoft@lemmy.ml 5 points 1 day ago

I'll just adb install those same apps from f-droid. But my hope is that I will be using mobile linux more and more as a daily-driver, until it eventually replaces Android 100%

[-] balsoft@lemmy.ml 13 points 1 day ago* (last edited 1 day ago)

I think this is roughly it:

  1. Magnetic beads manually strung on a thread, each one representing a single bit
  2. Punch cards/tapes
  3. Single-line text editors, for use on a teletype (a-la ed or qed - which still somewhat alive as sed)
  4. Multi-line, or "visual" editors, for use on the terminal (a-la vi)
  5. Modern IDEs
[-] balsoft@lemmy.ml 49 points 1 day ago* (last edited 1 day ago)

When palestinians capture mostly POWs, it's called "hostages" and "torture". When israelis capture mostly civilians and then actually torture them, it's called "detention". Get your nomenclature right folks, or you're an antisemite!

[-] balsoft@lemmy.ml 2 points 2 days ago* (last edited 2 days ago)

Imagine thinking of population and living as efficiency first and not wellbeing.

Ultimately if we want for 8 billion people to survive on this planet, we have to be somewhat efficient. If you spread out all current human population to a typical rural density (100/km^2) you get 80E6 km^2, or about all habitable land mass on earth. This leaves no areas for anything but human settlement. What you are advocating for is an infinite sprawling suburbia with not even a national park in between, which just sounds like a hellscape.

This is not taking into account that this will require everyone to use transportation to get anywhere (rather than a well-planned city where all daily destinations are a 5-10 minute walk), and transportation at those scales won't be efficient either - if we go with cars we get a network constantly jammed, insanely polluting highways, if we go with rail it would either take an insane amount of rail or the "last mile" would actually be 10 km with little to no infrastructure. In any case it would take an insane amount of time when you need to go somewhere uncommon, like a medical professional specializing in your rare disease, or a DnD hangout, or a scientific conference, whatever.

Other essential services will also be very inefficient like electricity (imagine just how much wiring we would need), or water supply and sewage (which requires piping and dedicated sewage treatment facilities), or emergency response (imagine the amount of deaths because we can't staff enough emergency stations to cover all the sprawl).

I'm not just talking about efficiency in the capitalist sense of profit, I'm talking about the basic sense of the amount of resources required to keep humans alive. We simply will not be able to sustain everyone living in a rural-like setting with a modern quality of life (like access to modern medicine, electricity, running water and internet). There is not enough land and resources on this planet to live like that. The fact that you and other people can do that is because they are (indirectly) subsidized by the city folk, mostly so that there is someone to work all those out-of-town agriculture jobs.

Also, the great thing about not living in a city is the fact you can grow your own food reducing the need for incredible amount of supporting land around you.

If you grow your own vegetables, you're using more land for your vegetables than if you bought them from someone else, because economies of scale make agriculture much more efficient. And in any case I grow some tomatoes and celery on my balcony, you can do that in a city too with proper planning.

Cities are sadness and misery factories, and some of the most polluted places humans have ever managed to create.

Have you ever been to a well-planned car-free (or at least less-car-infested) city? It can be a quiet cozy place with lots of communities forming, lots of green spaces, and access to nature within 10-15 minutes by train. The thing you hate about cities is probably not cities, it's cars and car-centric planning with suburban sprawl (which is ironically what you seem to be advocating for).

I've also lived a big chunk of my life in the forest, and I wanna do that again because I like forests. But I won't pretend it's sustainable for all humans to live like that. This must be the last refuge for those who truly love nature and/or want to work agriculture, which is a very low percentage of the overall population.

[-] balsoft@lemmy.ml 1 points 2 days ago* (last edited 2 days ago)

No, obviously it is just the most profitable, which is the only thing that matters under capitalism. With better planning we could totally use sustainable farming techniques, and have comparable yields.

And I don't know what you are on about with cities. Cities are the densest, and thus most efficient way of human settlement. Other forms of settlement are less dense, therefore require more land, therefore leave less land for agriculture (and result in higher transportation costs) which means agriculture has to have higher yield per unit of area.

[-] balsoft@lemmy.ml 11 points 3 days ago

It's very niche, but the only thing I could come up with is Kvevri, a traditional Georgian winemaking vessel. They're sold today (and still used for their stated purpose, aging wine), I've personally seen kvevris with the exact same shape buried in a wine cellar of 12th century monastery, and at least going by the article they're like 8000 years old, and haven't changed much in that time.

My other ideas were:

  • Bricks (turns out the earliest sun-dried mudbricks, which are very different from modern ones)
  • Concrete (turns out it changed a whole lot since the Romans, modern concrete is much easier to pour, sets faster and is much stronger)
  • Nuts & bolts (initially were hand-crafted and non-interchangeable - yuck!)
  • Knives (I'll let knife enthusiasts speak about that one)
[-] balsoft@lemmy.ml 2 points 3 days ago

Wheels have definitely changed a lot though.

[-] balsoft@lemmy.ml 32 points 3 days ago

I think it depends; some smart code is good actually, think 0x5f3759df. As long as you properly document it and leave plenty of comments. This one is not smart though, at best it's what I would call witty.

[-] balsoft@lemmy.ml 12 points 4 days ago* (last edited 4 days ago)

Haskell's runtime system is indeed magic, the fact it uses monads is just a consequence of monads being useful for this application. Monads themselves are not too complicated.

[-] balsoft@lemmy.ml 45 points 4 days ago* (last edited 4 days ago)

I'll assume you know Python, just so that we can speak the same programming language. (Also, this will make type theorists and category theorists cringe. I know what I'm describing is not generic enough, but it gets the point across)

A Monad is any type which "contains" values of arbitrary other types (think: list, set, etc) - let's call it the "container" type -, and for which it makes sense to define two operations: unit (you might see it called return in other places but this is very confusing, ignore it) and bind (a.k.a >>= operator).

unit is really easy. It just takes a value of the contained type and returns our container type with that value inside it. E.g. for a list, unit(1) == [1], unit("a") == ["a"]. Here is how we might define unit for a list:

def unit(a):
    return [a]

bind is a bit more complicated, but stick with me. bind takes two arguments. The first argument is a value of our container type, and the second argument is a function which takes the contained value and returns a container (it can have a different contained type, but must have the same container type). Note that we can pass any function we like to bind as the second argument, as long as the types are right.

For example, here is how we might define bind for a list:

def bind(lst, fun):
    new_lst = []
    for element in lst:
        new_lst.extend(fun(element))

    return new_lst

This definition applies the function to every element in the provided list, and returns the list with all the returned elements concatenated.

This definitely sounds weird for a list, but it does make sense in a particular context: describing computations which can produce multiple results.

Let's say we have two functions, one plus_or_minus(a) = ±a:

def plus_or_minus(a):
    return [a, -a]

And another, double_or_halve(a) = a * 2^(±1):

def double_or_halve(a):
    return [a * 2, a / 2]

Then we can apply them in sequence, using unit to create our starting list, and bind to apply the functions:

bind(
    bind(
        unit(1),
        plus_or_minus
    ),
    double_or_halve
)

What we get in the end is a "flat" list: [2, 0.5, -2, -0.5], listing all possible outcomes of our computations. This can even be slightly useful in some scientific settings.

If this all sounds esoteric, don't worry, for a list in Python it kind of is! However, some languages like Haskell provide a convenient syntax sugar for monads, which allow you to write monadic expressions as though you are writing imperative code, like this:

do
  a <- pure 1
  b <- plus_or_minus a
  double_or_halve b

And convenient operators, to write concise code like this:

pure 1 >>= plus_or_minus >>= double_or_halve

(Haskell standard library actually provides us with a definition of Monad, and its implementation for a List, such that both these examples are equivalent to the python one)

Hopefully you can start to see that with tooling like this, even a List monad can be occasionally useful.

But the main benefit of Monads comes when you start defining them for other types from the algebraic type land. Take for example Maybe - haskell's equivalent of Python's deprecated Optional, or Rust's Option. It is a type that can either contain a value or nothing at all. In python speak, it is

Union[a, None]

It is also a monad, quite trivially so.

Here's unit for this type:

def unit(a):
    return a

And here's bind:

def bind(opt, fun):
    if opt is None:
        return None
    else:
        return fun(opt)

With this monad we can combine "fallible" computations, i.e. computations that can fail for some inputs.

Take for example this:

def reciprocal(a):
    if a == 0:
        return None
    else:
        return 1 / a

This "fails" when the input is zero.

def minus_one(a):
     return a - 1

This function never fails.

We can combine multiple operations like this, guaranteeing that they never get None as an input:

bind(
    bind(
        bind(
            unit(1),
            minus_one
        ),
        reciprocal
    ),
    minus_one
)

(this returns None, but it never calls minus_one(None))

Or like this:

bind(
    bind(
        bind(
            unit(0.5),
            reciprocal
        ),
        minus_one
    ),
    minus_one
)

(this returns 0)

Once again this is much more elegant in Haskell: pure 1 >>= minus_one >>= reciprocal >>= minus_one or pure 0.5 >>= reciprocal >>= minus_one >>= minus_one

Notice how the structure of bind and unit calls is the same for both the list and the optional. This allows us to write functions which operate on arbitrary monads, which makes them useful for hundreds of seemingly very different types; it also allows Haskell to make syntax sugar which makes code more readable and understandable across dozens of different domains. It unifies a lot of different concepts into one "API", making it much easier to write generic code that encapsulates all those concepts.

Just as a glimpse of how powerful this is, a typical project structure in Haskell is to define your entire application domain (serving web pages, querying an SQL server, writing data to files) as a single monadic type; explaining this takes a lot more time, effort, and monad transformers.

However, the most useful part of Monads in Haskell is difficult to describe in Python. It is the fact that Monads perfectly encapsulate the "side effects" of a program, i.e. how it interacts with the real world around us (as opposed to side-effect-less computations). Haskell actually defines all side effects as functions which take and return the entirety of the "real world" (sounds insane, but it's actually really elegant); think something like this (python syntax):

def print(a: RealWorld, string: str) -> RealWorld: # <...>

And the side effect is then thought of as the difference between the RealWorld the function takes as argument and returns.

In order to take values from the real world (think: read the value from stdin, a-la python's input), Haskell then defines an IO type, which "contains" some value a which was "taken" from the real world. The details are deliberately hidden from the programmer here, so that you can't just "unwrap" the IO value and take the "contained" value from it from your side-effect-less function; you have to be inside the IO monad to do anything with the value. Under the hood it is defined as something like this (python syntax):

type IO[a] = Callable[RealWorld, (RealWorld, a)]

(don't dwell too much on the details here, it is admittedly confusing)

So, print is actually defined closer to this:

def print(string: str) -> IO[]:

(which can be read as: take a string and return some action in the real world, which doesn't return anything)

And getLine (Haskell's analog of python's input) is defined something like this:

def getLine() -> IO [str]:

(which reads: return some action in the real world, which returns a string)

This means that you can technically "call" both print and getLine from side-effect-less code, but they will simply give you an opaque value of type IO, which you can't do anything outside the IO monad. So that you can do anything with this type, the main function in Haskell is defined something like this:

def main() -> IO[]:

This then allows you to combine getLine and print as follows:

def main() -> IO[]:
    return bind(getLine(), print)

This reads one line from stdin and prints it to stdout.

The actual Haskell function looks like this:

main = getLine >>= print

Neither the getLine nor the print calls actually executed any code that read or printed anything; that code was executed by some mysterious "runtime" which first called the main function, got an IO () operation from it, and then executed that operation in its entirety.

This is probably very confusing; worry not, it will be, we're trying to do this in Python! I swear it makes much more sense in the context of Haskell. I highly recommend reading https://learnyouahaskell.com/chapters to learn more.

As fun exercises to make sure you understand monads, think of the following:

  • Can you come up with a (generic) type which isn't a monad?
  • Are functions monads? (hint: the answer is contained in this comment)
  • Is it possible for a type to be a monad in multiple different ways? Think of examples.
[-] balsoft@lemmy.ml 25 points 5 days ago

Yes, and if you fall down far enough you won't get any grants to do any research, and "forced" to go back to teaching/mentoring. Both of those things tell a lot about the state of high-level education and academia in the west.

10
submitted 3 months ago by balsoft@lemmy.ml to c/pics@lemmy.world

cross-posted from: https://lemmy.ml/post/33203710

Sunrise in Wadi Rum desert. Taken from my phone with OpenCamera's stacked HDR.

32
submitted 3 months ago* (last edited 3 months ago) by balsoft@lemmy.ml to c/pics@lemmy.world

cross-posted from: https://lemmy.ml/post/32177363

Moon rising during sunset. Taken from Gombori mountain. Nikon D700, 85mm, cropped.

8
submitted 4 months ago by balsoft@lemmy.ml to c/pics@lemmy.world

cross-posted from: https://lemmy.ml/post/31830215

I liked posting a picture here so I think I will try to do it weekly :)

This is what the dawn of January 1st 2025 looked like for me. We've slept in my van through the night to get this view. The temperature was about -20℃ but it was worth it in the end.

The flats in the picture is the frozen Lake Paravani and the mountains are the Samsari ridge.

6
submitted 4 months ago by balsoft@lemmy.ml to c/pics@lemmy.world

cross-posted from: https://lemmy.ml/post/31459711

Since today is my first cake day, I've decided it's time to post instead of commenting. This is a picture I took last month on my phone through binoculars. Taken from Gomismta, the mountains you see are the Main Caucasian Ridge.

view more: next ›

balsoft

joined 1 year ago