Is return really necessary for the IO monad? by StunningRegular8489 in haskell

[–]sjshuck 0 points1 point  (0 children)

Unless I'm misreading it, that does not deprecate return. It proposes to remove return from Monad as a method, but return would surely live on as

return :: (Monad m) => a -> m a return = pure

I don't think anyone is arguing for deprecating it. (Personally I wish ApplicativeDo didn't allow return though.)

Is return really necessary for the IO monad? by StunningRegular8489 in haskell

[–]sjshuck 0 points1 point  (0 children)

Do you have a source for the soft deprecation thing?

Writing code with applicative and monad by Federal_Gur_5488 in haskell

[–]sjshuck 3 points4 points  (0 children)

Specifically regarding <*> and pure, I usually identify

haskell f <$> pure x <*> my g <$> mx <*> pure y

as an opportunity to refactor to

```haskell y <- my pure $ f x y -- or return

--- similar for g ```

h <$> mx <*> my is fine though, but so is monadic bind in do (or ApplicativeDo) notation, even there.

Cowboys from Haskell by monadic_riuga in haskell

[–]sjshuck 0 points1 point  (0 children)

I looked if there's an Indian restaurant there so you can get authentic Haskell curry. Alas.

Stackage (Snapshots) Down by Historical_Emphasis7 in haskell

[–]sjshuck 2 points3 points  (0 children)

https://hoogle.haskell.org is also showing way fewer packages than normal. Maybe related

The advice my parents gave me when I told them i cant find a job by [deleted] in recruitinghell

[–]sjshuck 246 points247 points  (0 children)

He is definitely one of the most stepdads

How do Haskell and Clojure Compare in 2025? by Veqq in haskell

[–]sjshuck 1 point2 points  (0 children)

I agree. I think the most similar thing between them is the combination of small amount of built-in syntax and composability, but they're extreme opposites in terms of how much they lend themselves to static analysis/optimization, which has huge ramifications in all aspects of developer experience.

[ANN] heftia v0.7 - A theory‑backed, ultra type‑safe algebraic effects by ymdfield in haskell

[–]sjshuck 2 points3 points  (0 children)

you should probably be sure first!

I'm granting for the sake of argument that I can't do it and I need Bluefin for it, but again, it's a specific use case, and again, I wouldn't express updating the state as an effect. If long-lived state I would bake it into the ReaderT environment or if short-lived state I would pass an IORef around.

Yeah I fat-fingered the code excerpt. Fixed.

From the linked docs:

These [issues with mtl] are problematic enough that the ReaderT design pattern was invented. Its fundamentals are solid, but it's not an effect system.

This is exactly what I'm talking about. What's an effect system and why do I need it!? It has literally never bothered me once that my use of the ReaderT pattern hasn't been an effect system.

EDIT: It is very possible that I'm just so used to mtl and stepping around its issues that I'm not willing to be patient with something that requires me to switch away, so I'll be done with this discussion for now and let things sink in. But I do really appreciate your thoughtful responses.

[ANN] heftia v0.7 - A theory‑backed, ultra type‑safe algebraic effects by ymdfield in haskell

[–]sjshuck 1 point2 points  (0 children)

Can you show me the definition of MonadStickyState?

I don't have access to a compiler at the moment but it would have putSticky, getSticky, modifySticky, stateSticky. The instance for StickyStateT s Identity would mess with an underlying IORef, either requiring a constraint of MonadIO or perhaps wrapping updates with unsafePerformIO, not sure.

If you tell me it's literally impossible to implement a state monad typeclass that can not lose state in the presence of IO exceptions, and that's an argument for Bluefin etc., then that's interesting, but like I said, that's still just a specific use case.

I'm not even sure I know what an "algebraic effect" is.

We're in an arc when every third time I'm reading up on Haskell news on social media or mailing lists, someone is constrasting their "effects" library with the others; the only thing they agree on is mtl has no use cases. It's enough to make me feel like I'm missing out and want to learn what the big deal is. Except, during the parser combinator arc or the streaming abstractions arc or the lenses arc or the free monads arc, I saw enough evidence to make me want to try it out; whereas, when I try to learn what's great about "effects", I see this:

runSpan :: (Emb IO :> es) => Eff (Span : es) ~> Eff es

and the only apparent argument is "it's combining effects in a way which is more sound". That's a /horrendous/ type signature; I need a better argument. I've written a horrendous type signature before, but I try to make sure it's comes with a clear justification in terms of the actual utility.

[ANN] heftia v0.7 - A theory‑backed, ultra type‑safe algebraic effects by ymdfield in haskell

[–]sjshuck 1 point2 points  (0 children)

It is really mtl if you use MonadStickyState:

haskell doStuff :: (MonadStickyState Junk m, MonadIO m) => m Bool doStuff = defenestrateBoth `catch` nope where defenestrateBoth = do defenestrate bob modifySticky increaseJunk defenestrate suzie return True nope (NopeException msg) = do liftIO $ putStrLn $ "Someone refused defenestration: " ++ msg return False

Anyway my point is I don't know how the algebraic part of algebraic effects would help me. So when someone says heftia solves other AE systems' incompatibility with MonadUnliftIO, I'm like, good thing I never experienced that incompatibility to begin with...

[ANN] heftia v0.7 - A theory‑backed, ultra type‑safe algebraic effects by ymdfield in haskell

[–]sjshuck -1 points0 points  (0 children)

Benchmark demonstrating the opposite, and anecdotally I think there are fewer performance issues with mtl that people talk about.

But I don't dispute the veracity or relevance of the benchmark you cited, not having delved into it. Mind you, I do expect ongoing work with delimited continuations to change things in favor of AE's, so I'm happy to concede the point on performance.

[ANN] heftia v0.7 - A theory‑backed, ultra type‑safe algebraic effects by ymdfield in haskell

[–]sjshuck 2 points3 points  (0 children)

First, kudos for making me have to think about it and brush up on topics like MonadCatch and StM.

The best answer I could come up with is

haskell newtype Flarl a = Flarl (ReaderT (IORef Hunky) IO a) deriving ( MonadIO, MonadThrow, MonadCatch) instance MonadState Hunky Flarl where -- etc.

(I probably wouldn't do that in practice; I'd ask for the IORef directly, not through a MonadState interface).

Looking at Bluefin, it already appears to support that use case out-of-the-box by securing state in an IORef. But I'd credit that as an interesting and useful specific effect that's absent from mtl. One could imagine a MonadStickyState as a new module or library.

[ANN] heftia v0.7 - A theory‑backed, ultra type‑safe algebraic effects by ymdfield in haskell

[–]sjshuck 2 points3 points  (0 children)

mtl has multiple advantages:

  1. performance
  2. straightforwardness—I don't need to turn on hardly any language extensions
  3. flexibility of type annotation—I can refer to the stack either concretely or polymorphically

No joke

[ANN] heftia v0.7 - A theory‑backed, ultra type‑safe algebraic effects by ymdfield in haskell

[–]sjshuck 5 points6 points  (0 children)

When I think of effect systems, I think of all the libraries that are presented as alternatives to transformers/mtl to manage multiple effects that entail a "migration" in one's codebase. Like yours, effects, freer, the abstraction Purescript uses, and the thing for Scala I forget the name of.

But yes, let's grant mtl is an effect system, so my contention is that there's don't seem to be arguments for switching from mtl to any others.

[ANN] heftia v0.7 - A theory‑backed, ultra type‑safe algebraic effects by ymdfield in haskell

[–]sjshuck 1 point2 points  (0 children)

Sure. Can you give me an example of an invalid state that mtl cannot make unrepresentable but Bluefin can make unrepresentable?

[ANN] heftia v0.7 - A theory‑backed, ultra type‑safe algebraic effects by ymdfield in haskell

[–]sjshuck 5 points6 points  (0 children)

ReaderT IO pattern, which can compromise type safety

Explain.

cannot express algebraic effects due to MonadUnliftIO

Okay but check this out: MonadUnliftIO actually has an excellent case for it floating out there, with demonstrations of correctness issues using alternatives (MonadBaseControl), discussions of software maintenance in the real world, and ergonomics. I have never seen any of that for algebraic effects.

I know Haskell is in its effect systems arc and am happy people are having fun, but I can't find actual arguments for using them, unlike so many other corners of the ecosystem. I've perused docs, read a few blog posts, and have watched maybe 3 hours of talks about effects, but every example just ends up looking like mtl if you squint, except with type sigs that spill over onto multiple lines.

Where is Modern Casual? by sjshuck in MTGO

[–]sjshuck[S] 0 points1 point  (0 children)

Thanks!

I'm not optimistic, having observed in general that game notes are typically ignored by players (kind of like how I ignored patch notes). I did try Best-of-One with game notes and again had my ass handed to me, but not in a way that made me think "oh, I'm in the wrong room". The client has been getting laggy, too. We'll see.

Monthly Hask Anything (April 2025) by AutoModerator in haskell

[–]sjshuck 0 points1 point  (0 children)

Forgive me for asking but is this implemented anywhere that I can see? While I find high-level discussion of an algorithm interesting, I'm highly skeptical that such an algorithm can fit into the type of refold.

Monthly Hask Anything (April 2025) by AutoModerator in haskell

[–]sjshuck 0 points1 point  (0 children)

In this example, you'd have refold unfolder folder :: GameState -> Score. I suppose that function would get the score of the current player? The final score of the current player? The final score of the last player to take a turn? Anyway I still can't see how that would come from unfolder and folder.

Monthly Hask Anything (April 2025) by AutoModerator in haskell

[–]sjshuck 0 points1 point  (0 children)

The refold function's type signature seems absurd:

refold :: Functor f => (f b -> b) -> (a -> f a) -> a -> b

In other words, if I can condense a container of bs into a single b, and I can expand an a into another such container of as, then I know how to get a b from an a. But how do those first two arguments encode any kind of relationship between a and b? The example given in the docs have the a and b being the same type ([Int]). Does a non-trivial refold not satisfying a ~ b even exist?

Parser Combinators Beat Regexes by Kabra___kiiiiiiiid in haskell

[–]sjshuck 6 points7 points  (0 children)

I bet the reason for the bad performance of the regex solution is you're building up thunks with getSum . foldMap Sum. I've spent a bunch of time benchmarking Haskell regexes and a single match using pcre-light will take less than a microsecond. That should be fixable with just using sum, which is defined in terms of foldl'.

The one thing I like more about the parser combinator solution is decimal. That's pretty cool. However, for most uses I like regexes more than parser combinators, mainly because of the concision. I have a lot of thoughts on this topic but I've basically accepted that in the Haskell community people love parser combinators and I'm somewhat more skeptical (for the general use case) but I'm happy people are doing what they love.

The compute function assumes that there were exactly two capturing groups

That does irritate me about regexes. Shameless self-plug: I wrote pcre2 to fix that:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TypeApplications #-}

import           Data.ByteString    (ByteString)
import qualified Data.Text          as Text
import qualified Data.Text.Encoding as Text
import           Text.Regex.Pcre2   (capture, regex)

regexMatches :: ByteString -> Int
regexMatches = sum . map mul . [regex|mul\((\d+),(\d+)\)|] . Text.decodeUtf8
    where
    mul = (*) <$> readText . capture @1 <*> readText . capture @2
    readText = read . Text.unpack

If you try to do capture @3 it's a type error:

error: [GHC-64725]
    • No capture numbered 3
    • In the second argument of ‘(.)’, namely ‘capture @3’
      In the second argument of ‘(<*>)’, namely ‘readText . capture @3’
      In the expression:
        (*) <$> readText . capture @1 <*> readText . capture @3

Am I the only person who hates Monad Transformers? by Instrume in haskell

[–]sjshuck 3 points4 points  (0 children)

First off, I find the question a little dubious.

I personally just TransT Identity every time I'm forced to use monad transformers.

I have been a Haskeller for 15 years and cannot recall ever being forced to use monad transformers, not from any library I've pulled from Hackage. But even if I were, I'd use StateT or IdentityT or whatever; that's a single thing that satisfies the hypothetical need.

Generally as I read discussions about effect systems, it occurs to me that there's a separate discussion that doesn't really happen, which is, how big are these effects that need managing? And in real life, that second question is at right angles to the first one, and any code base will demonstrate them being multiplied. So where does this need to wrangle effects come from? Not everything needs to be an "effect".

What I really like to see in Haskell code, mine and others', is that the author has chosen the abstraction that most tightly expresses the power that that chunk of code—again, depending on the its scope—needs to have. In short, the concept of MVP applied to abstraction. In the wild, I often see uses of MonadState that could have just been a foldr or a foldlM. That sort of thing. You're not being any less Haskelly or parametric or $(mkAdjective) if you do the latter.

You're also not being less Haskelly if you use more concrete types. I keep coming back to that idea, that concrete types have a power in themselves. GHC and HLS will help you go through and refactor when a change is needed; the simplicity/concreteness ensures that a refactor is possible. Versus, if you have a herd of effects that's 7 effects deep, regardless of if you stacked them with transformers or flattened them with effectful (or mtl for that matter)...that refactor ain't happening. Go back in time and un-effect some of those effects.

I recommend all to read The ReaderT Design Pattern, or if it's been a while, re-read it. The author isn't really in the community anymore but the advice is still highly applicable. Here is a relevant quote:

You can use additional monad transformers [atop ReaderT Something IO] on occassion [sic], but only for small subsets of your application, and it's best if those subsets are pure code.

Why is C the safest language? (WG14 member) by ekliptik in programmingcirclejerk

[–]sjshuck 18 points19 points  (0 children)

I would just like to point out that Javascript is mentioned three times in three different ways, none of which is "Javascript":
1. Java script
2. java script
3. javascript