• 0 Posts
  • 91 Comments
Joined 1 year ago
cake
Cake day: June 10th, 2024

help-circle
  • If we can ignore “checks and balances” for real,

    Step 0: declare the US constitution mostly void, to prevent stupid hacks like “states rights” or “fed can only regulate interstate commerce” or whatever. Keep its remnants around to ensure institutional knowledge and capabilities are preserved, until a transition to better institutions is implemented. Declare all capitalist parties illegal, seizing their assets. Then move on to the plan:

    1. Immediately nationalize all rented-out residential buildings and set up social housing. Introduce a hard limit of two residential units per person. Prohibit commercial entities from owning residential properties.
    2. Immediately nationalize all healthcare and pharmaceutical organizations
    3. Immediately nationalize all organizations of national importance (high number of employees, monopolies, military-adjacent)
    4. Require all other businesses to be turned over to employees, co-op style, within a certain timeframe (this is to allow for graceful handover at least from those small business owners who cooperate). Modify tax codes accordingly
    5. Require a merit-based entry system into universities and colleges, forcing all higher education to be free. The deciding factor of which university you attend is your exam scores. Set up funding for the institutions appropriately.
    6. Everyone with over a billion dollars in assets (before the previous steps) get their property confiscated, goes to jail, and has to work at minimum wage until they repay what they have stolen from the people. Those who repent and collaborate may be released earlier under certain conditions, like a hard limit on earnings and restrictions on travel.
    7. Introduce a plan to transition away from animal agriculture, with a set timeframe to completely prohibit animal-based foods and other unnecessary animal suffering
    8. Introduce a plan to transition all densely populated areas away from car transportation, with a set timeframe to completely prohibit private vehicles in all cities
    9. Introduce a plan to transition from fossil fuel use to sustainable energy sources, with set timeframes for net-0 and complete elimination of fossil fuel use. Limit use of oil derivatives, with a plan to reduce them to minimum necessary (such as medical uses)
    10. Prohibit all organized religion. Make proselytizing a crime similar to fraud. Mandate all education be based on materialism (and therefore atheism)
    11. Allow formation of various socialist or communist parties. Require free, competitive, ranked-choice elections for all positions within parties. Require ranked-choice voting for all positions in the Senate. Require proportional representation for House elections. Introduce a plan to replace POTUS with an executive committee, with halves of the committee elected in a staggered way via proportional representation to ensure both continuous, stable leadership and adequate representation of new ideas. Introduce a plan to reform the judiciary with significantly more checks on the supreme court. Require similar election schemes for state&local legislatures and executives.
    12. Immediate pardons for persons imprisoned for anti-capitalist viewpoints or actions, drug possession or consumption (maybe some others too)
    13. Help socialist, communist or otherwise leftist movements worldwide, but especially in the Americas. Aim towards a pan-american union of socialist republics with freedom of movement, free trade, resource sharing and other collaboration
    14. Introduce a requirement for 50% of all positions within a certain level of parties and government to be filled by women. Enshrine abortion and LGBT rights into law. Introduce a long-term plan to eliminate the concept of gender from society
    15. Introduce a long-term plan for the state to wither away and transition to communism, whether it is commune-based anarchism or collectivism

    If we manage to push through all these changes, I wouldn’t want to be reelected for any amount of terms.





  • As a senior engineers writing Haskell professionally for a number of years, I’ve found it much simpler to teach about Monads after having taught about Functors and Applicatives first, because there’s a very natural, intuitive progression, and because most people already have an intuitive grasp of Functors because map is cribbed so commonly in other programming languages.

    I agree! I just wanted to explain what Monads are, standalone, and avoid introducing any other concepts.


  • It’s a “programmable semicolon” or “decorated-function composition”

    “programmable semicolons” is wrong, you can have that without Monads, and in fact Haskell has a do-notation for Applicative. “decorated function composition” is a bit vague, I think I see what you mean but it’s not too helpful.

    It’s just an interface for a generic type that requires two specific functions to be implemented. Understanding why it is so useful is the tricky part.





  • balsoft@lemmy.mltoProgrammer Humor@programming.devMonads
    link
    fedilink
    arrow-up
    5
    ·
    edit-2
    8 days ago

    This is actually a good alternative explanation, as long as you clarify it a bit.

    What is meant by “container” type is that it’s possible to

    1. “Put” a single thing into our container (unit/pure)
    2. “Modify” the insides our container (map/fmap), without “taking any values out”

    Take for example a list.

    unit is simple, as I’ve described in my comment:

    def unit(a):
        return a
    

    Map is also fairly straight-forward, just applying a given function to every element of the list:

    def map(fun, lst):
        new_lst = []
        for element in lst:
            new_lst.append(fun(element))
        return new_lst
    

    Then your final operation (“flattening” the container) is traditionally called join. It concatenates a list of lists into a single flat list:

    def join(lst):
        new_lst = []
        for element in lst:
            new_lst.extend(element)
        return new_lst
    

    (you might notice that it is extremely similar to both map and bind)

    This allows us to define bind from my other comment (which you call flatMap) in terms of join and map:

    def bind(lst, fun):
        return join(map(fun, lst))
    

    Or, if you already have a bind (and unit) defined, you can define join and map as follows:

    def join(lst):
        return bind(lst, unit)
    def map(fun, lst):
        return bind(lst, lambda x: unit(fun(x)))
    

    Showing that a type defining unit and bind is equivalent to a type defining unit, join and map - they are both equivalent definitions of a monad, you can derive one from another and vice versa.

    Historically, the unit+bind definition is more popular and aligns with what most functional languages do, so I went with it for my explanation. But yours is probably a bit easier to understand for an FP outsider.


  • balsoft@lemmy.mltoProgrammer Humor@programming.devMonads
    link
    fedilink
    arrow-up
    47
    ·
    edit-2
    8 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.



  • In my cases I has to solve same code conflicts multiple times during a rebase, so I just don’t try them when hit with conflicts.

    Yeah if you have two branches, both with a bunch of commits which all modify the same areas of code, and reordering the commits doesn’t help, I can see how it is easier to merge.

    I fail to see the benefits of “clean” git history

    Well, if the commit history is clean and mostly linear, it’s much easier to read, understand and review. git blame will also be much nicer which is really important for debugging big codebases. Of course it’s a tradeoff, as usual.




  • Specifically screwing up rebase. It is recoverable, but very annoying.

    WDYM? Typically git rebase --abort will “just work”. If you have specifically done something really wrong, just look into git reflog and then git reset --hard to whatever commit you were before the rebase.

    Pushing your commit without fetching

    Git won’t allow you to do that if you set up your server properly. It will force you to pull first. I have [pull] rebase = true in my settings so that it always rebases my commits instead of merging them, which makes for much cleaner history.

    Continuing on a branch even after it was merged.

    This generally shouldn’t be a problem, you can just rebase the branch afterwards and it will be fine (the common commits will typically just be dropped).




  • I would honestly prefer it if more websites just did that and gave you access to whatever they have about you in their database. Would be much easier to figure out which data they actually store about me. If you set up the access lsits appropriately it could be OK from the security perspective too (of course better to do it over something other than SQL, but who am I to judge).