Hacker Newsnew | past | comments | ask | show | jobs | submit | tome's commentslogin

How did your tests pass if you didn't handle state?

Because it is also possible to write tests that don't adequately capture real-life requirements.

It was an MQTT server, and the tests basically went "if we have these subscriptions, then...", but no subscriptions ever got actually stored by the server.


> People nowadays are just desperate to have a diagnosis. Everybody wants to be special and unique

I've never managed to understand this when it comes to autism. Autism used to be considered something as extreme as a severe disability (e.g. Rain Man), and latterly with the inclusion of Asperger's into the spectrum, at the very least a collection of undesirable behavioural characteristics. Do people really want to be diagnosed with something wrong with them, or has the perception of autism shifted to at least neutral (if not positive)?


I think it's useful to look at the alternative. It is still socially acceptable, even among progressives, to viciously mock people who are socially awkward and simply write them off as undeserving of help. At least with autism many people extend some degree of sympathy and willingness to help.

Yes. Social awkwardness then is not seen as a character flaw but more like a birth defect.

At the risk of offending some people, I think it's similar to why people lie about their dog being a "service dog".

It may genuinely be that their dog is their emotional support, but it's ultimately a bit of selfishness and wanting to be treated preferentially in a world that feels crowded and rigid.


Is it necessary that a monad "builds up a computation and then runs"? In fact it's very hard for a monad to do that because the type of bind is

    (>>=) :: m a -> (a -> m b) -> m b
so you can really only make progress if you first build a bit (`m a`), then run it (to get `a`) then build the next bit (applying `a` to `a -> m b`), then run that. So "building" and "running" must necessarily be interleaved. It's an odd myth that "Haskell's IO purely builds an impure computation to run".

Are you saying "monad" is a synonym of "interface"?

Not a synonym, but `Monad` is one of the commonly used interfaces in Haskell (not the only one).

OK I think I understand now, thank you. My takeaways:

1. Yes, Zig is doing basically the same thing as Haskell

2. No, it's not a monad in Zig because it's an imperative language.


It still is a monad. It's just Zig doesn't have language support for monads, so it's less ergonomic.

Just as modular addition over ints in Zig forms a group, even if Zig has no notion of groups. It's just a property of the construct.

Laziness has nothing to do with it.

What that means practically for Zig, I'm unsure.


And for comparison, here's Haskell's (or rather Bluefin's) equivalent of Zig's `Io` parameter:

https://hackage-content.haskell.org/package/bluefin/docs/Blu...


> 1. a description of how to carry out I/O that is performed by a separate system

> 2. does the I/O inside the function before returning

How do you distinguish those two things? To put my cards on the table, I believe Haskell does 2, and I think my Haskell effect system Bluefin makes this abundantly clear. (Zig's `Io` seems to correspond to Bluefin's `IOE`.)

There is a persistent myth in the Haskell world (and beyond) that Haskell does 1. In fact I think it's hard to make it a true meaningful statement, but I can probably just about concede it is with a lot of leeway on what it means for I/O to be "performed by a separate system", and even then only in a way that it's also true and meaningful for every other language with a run time system (which is basically all of them).

The need to believe that Haskell does 1 comes from the insistence that Haskell be considered a "pure" language, and the inference that means it doesn't do I/O, and therefore the need that "something else" must do I/O. I just prefer not to call Haskell a "pure" language. Instead I call it "referentially transparent", and the problem vanishes. In Haskell program like

    main :: IO ()
    main = do
       foo
       foo

    foo :: IO ()
    foo = putStrLn "Hello"
I would say that "I/O is done inside `foo` before returning". Simple. No mysteries or contradiction.

https://hackage-content.haskell.org/package/bluefin/docs/Blu...


> I would say that "I/O is done inside `foo` before returning".

It is not. The documentation and the type very clearly shows this:

https://hackage.haskell.org/package/base-4.21.0.0/docs/Prelu...

> A value of type `IO a` is a computation which, when performed, does some I/O before returning a value of type a.

So your function foo does no IO in itself. It returns a "computation" for main to perform. And only main can do this, since the runtime calls main. You can call foo as much as you like, but nothing will be printed until you bind any of the returned IO values.

Comparing it to other languages is a bit misleading since Haskell is lazy. putStrLn isn't even evaluated until the IO value is needed. So even "before returning" is wrong no matter how you choose to define "inside".


I'm also pretty sure that its immaterial if Haskell does 1 or not. This is an implementation detail and not at all important to something being a Monad or not.

My understanding is requiring 1 essentially forces you to think of every Monad as being free.


Ah! My favourite Haskell discussion. So, consider these two programs, the first in Haskell:

    main :: IO ()
    main = do
      foo
      foo

    foo :: IO ()
    foo = putStrLn "Hello"
and the second in Python:

    def main():
      foo()
      foo()

    def foo():
      print("Hello")
For the Python one I'd say "I/O is done inside `foo` before returning". Would you? If not, why not? And if so, what purpose does it serve to not say the same for the Haskell?

My Haskell is rusty enough that I don’t know the proper syntax for it, but you can make a program that calls foo and then throws away / never uses the IO computation. Because Haskell is lazy, “Hello” will never be printed.

You can do this

    main = do
      let x = foo
      putStrLn "foo was never executed"
but you can also do this

    def main():
      x = foo
      print("foo was never executed")
What's the difference?

> It’s an extremely facile work and reads exactly like a high school essay: “In having his character consider execution to protect his and his family’s reputation, Doyle explored the societal expectations of Victorian masculinity and how men struggled with such pressures.”

Not to mention that that the character in this particular story is not actually struggling with debt, he simply discovers, somewhat incredibly, whilst researching for a newspaper story, that he can earn far more money begging than in his job as a reporter. There simply is no pressure, he just lacks integrity.


Is it even remotely appropriate to blame without first understanding? In which case, doesn't this perspective completely rule out the possibility of any appropriate blame?


> Is it even remotely appropriate to blame without first understanding?

Yet, blame is easy and satisfying and true understanding requires empathy and is hard and often unsatisfying.

The term "understanding" is fractal and infinite. Therefore Its 100% reasonable to find a stopping point and say "I blame you" (or, as you point out, otherwise, no one would ever be allowed to assign blame).

My comment is more about intent. The "seeking" word weights heavy. Many commenters are not seeking understanding, they are seeking satisfaction. Validation. The author of the post could have stopped much sooner if they were seeking blame, they could have chosen to build a caricature to heap more judgement upon. But they chose a more nuanced and exploratory path.

Even if the end result is blame or judgement. It's important that the purpose of the journey is clear. True understanding requires empathy, and it's really hard to empathize with someone you're actively trying to judge or vilify.


> > tax revenues are higher than ever, government spending is higher than ever, social programs and social spending is higher than ever

> Obviously every nominal value is going to be higher YoY

It's not just nominal. You can see on the Institute for Fiscal Studies website that, as proportion of GDP, public spending has not been notably higher than since the second world war:

https://ifs.org.uk/taxlab/taxlab-data-item/uk-government-spe...


> Effect systems are a trend that will go away

I'm willing to bet the contrary: that IO-wrapper effect systems are the future of Haskell (particularly Bluefin, but then that's my library, so I would say that).

> You can't statically guarantee that only, for example, the DB has side effects in a function

Yes, you absolutely can.


> No it is not high performance, but neither are any other Haskell effect systems

This is not true. IO-wrapper effect systems (in practice, effectful or Bluefin) have as good performance as Haskell's IO monad, that is to say as good as you can get in Haskell.


Yes but from what I understand at a loss of safety. You can decide if that is worth it but you aren't getting a free lunch.

that said, your library is really cool. : )


No, no loss of safety. Was there something in particular you were thinking of? With IO-wrapper effect systems you give up native multishot continuations (but you can always get them back by wrapping in LogicT).

You can look at my table of "A Comparison of Effect Systems at a Glance" to see all the tradeoffs:

https://hackage-content.haskell.org/package/bluefin-0.2.0.0/...


> No, no loss of safety. Was there something in particular you were thinking of?

This is second hand information and may apply more so to effectful then bluefin. I have just done some pretty minimal test projects with bluefin and effectful but I was told:

""" It's not too hard to make segfault if you organize your higher order effects just right.

It's been a while but i think you just return a continuation with the effect you just handled, and then all of a sudden it's not in scope and yet you need to still handle it.

And the tricks they use to make things go fast don't work in this case and things go boom """


That definitely doesn't apply to Bluefin. I can't rule out it applying to effectful, but it is careful to do dynamic checks to make sure you can't use effects in the wrong scope. Maybe you're thinking of eff (i.e. what started this thread)? Alexis King described how to get it to segfault in this video: https://www.twitch.tv/videos/1163853841 (now private, sadly).


> your library is really cool. : )

And thanks! Glad you like it. Feel free to reach out to me at any time if you'd like any help with it or have any questions or comments.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: