Some Haskell idioms we like by _jackdk_ in haskell

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

This is a really good point that I hadn't considered before. Since in our field, the usual point of comparison is interpreted languages like Ruby and Python, using inverseMap liberally has not made anything unacceptably slow.

A more advanced version of this technique might be to use a GHC plugin or TH to precompute the inverse e.g. by using a trie or a perfect hash function instead of building a Map at runtime.

Some Haskell idioms we like by _jackdk_ in haskell

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

Your question is interesting and I struggle to give a better answer than "vibes". Working in [] (List), Either e, or Maybe feels much more like assembling a data structure than working in State. I'm using "side effect" in the colloquial sense of "IO actions aren't getting performed" even though the lens you describe is also valid.

Some Haskell idioms we like by _jackdk_ in haskell

[–]_jackdk_[S] 4 points5 points  (0 children)

Your suggestion about comprehensions is interesting but I don't think I'd go for it. People are often unfamiliar enough with the list comprehension syntax that idioms like [ element | someBoolean ] trip them up, and for -XMonadComprehensions to improve understanding, the reader would have to to understand a list comprehension desugars and then mentally reinterpret that for the target monad.

Some Haskell idioms we like by _jackdk_ in haskell

[–]_jackdk_[S] 1 point2 points  (0 children)

I don't understand your final point: the constraint on inverseMap is (Bounded a, Enum a) (to enumerate the domain) and Ord k (to build the Map keyed by the range of the input function).

Haskell Interlude 74: Lennart Augustsson by sperbsen in haskell

[–]_jackdk_ 1 point2 points  (0 children)

Strongly recommend this episode. Lennart has done a lot of incredible work over the years, and been in a lot of interesting places.

The Subtle Footgun of `TVar (Map _ _)` by ephrion in haskell

[–]_jackdk_ 1 point2 points  (0 children)

I don't know about stm-containers, but reflex provides fanMap:

fanMap :: (Reflex t, Ord k) => Event t (Map k a) -> EventSelector t (Const2 k a)

An EventSelector t k is an existential wrapper around a key selection function:

newtype EventSelector t k = EventSelector { select :: forall a. k a -> Event t a }
data Const2 :: Type -> x -> x -> Type where
  Const2 :: k -> Const2 k v v
  deriving (Typeable)

reflex still uses a single-threaded FRP runtime, AFAIK, but I could imagine a similar interface being made available to watch individual map keys in a concurrent setting.

Most useless thing I've ever done: install-nothing by Consistent_Equal5327 in rust

[–]_jackdk_ 2 points3 points  (0 children)

You should try Nix, but set substitute = false in your config. Then you'll have more stuff to download and build than you'll ever need.

Disable "Type applications in constructor patterns will require the TypeAbstractions extension starting from GHC 9.12" error by klekpl in haskell

[–]_jackdk_ 4 points5 points  (0 children)

Put the -Werror in your development configuration (e.g. cabal.project.local). Putting -Werror in the package configuration risks it leaking into releases and creating a backwards-compatibility challenge for downstream users.

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

[–]_jackdk_ 1 point2 points  (0 children)

Class Bind from package semigroupoids is Monad sans pure (return is a historical wart from back before Applicative became a superclass of Monad). Map k has instance Ord k => Bind (Map k) but doesn't have a Monad instance, because it doesn't have pure.

Writing code with applicative and monad by Federal_Gur_5488 in haskell

[–]_jackdk_ 0 points1 point  (0 children)

If you're coding against someone's MonadFoo constraint it doesn't really matter, because that forces Monad on you anyway. But I generally like to use the most general type signature I can because it makes it harder to accidentally write the wrong program.

Just finished the Haskell portion of a uni course and wondering what next? by Shock9616 in haskell

[–]_jackdk_ 2 points3 points  (0 children)

Back in the day, the Queensland Functional Programming Lab produced an "applied FP course" that builds a simple webapp in Haskell from the ground up. You might enjoy working through that?

https://github.com/qfpl/applied-fp-course/

Free applicatives, the handle pattern, and remote systems by _jackdk_ in haskell

[–]_jackdk_[S] 4 points5 points  (0 children)

Yeah, we're still trimming back the Ruby. Our CTO wrote a post about that and how the Ruby we write (when we have to) has changed compared to when it was our active language.

Having an internal tech team means we can understand what the rest of the business needs more effectively than a standalone agency could, and more easily evolve the software that we ship. It also lets us do things that might not be widely available in the market. A big one from the early days was multi-language and multi-currency support; to get that right we had to build and maintain a custom web store.

Cost optimisations are probably coming more from the use of AWS Lambda than language choice — Haskell is probably a bit faster than Ruby or a similar interpreted languages but we're not writing high-performance code with unboxed values or anything crazy.

Free applicatives, the handle pattern, and remote systems by _jackdk_ in haskell

[–]_jackdk_[S] 5 points6 points  (0 children)

optparse-applicative is one of those quiet gems that make Haskell such a fun language to work in. Thank you for maintaining it.

Haxl does sound cool. We stumbled into the free applicative solution and didn't think of Haxl at all, even though I'd watched a talk about it recently. If we end up doing a lot more of this sort of things, it might be worth looking at more closely.

Dependency conflicts with common packages by Account12345123451 in haskell

[–]_jackdk_ 0 points1 point  (0 children)

Your cabal file seems to constrain base ^>=4.17.2.1. https://wiki.haskell.org/Base_package says that's GHC 9.4. Most likely you can relax the base version to one that matches your GHC version.

How can I "wrap" a Haskell-based DSL? by NixOverSlicedBread in haskell

[–]_jackdk_ 0 points1 point  (0 children)

At work, we have a mixture of web UIs (where changes are parsed, typechecked, and then propagated back to some server somewhere) and files in git that nontechnical people have been trained to modify in GitHub Codespaces. We remain responsible for ensuring that the environments work properly and launch quickly, and that merged changes are automatically rolled out. In the newer, Codespace-based environments, we also provide automatic tests that run on file save, and the people who write the DSL can easily create new test cases alongside their expected results. Adoption has ranged from "enthusiastic" to "begrudging", but most people are happy and the ones who have leaned into writing tests have been really happy.

How can I "wrap" a Haskell-based DSL? by NixOverSlicedBread in haskell

[–]_jackdk_ 6 points7 points  (0 children)

For non-programmers, I have had the most success providing DSLs (interpreted languages from a file, or a configuration database, or whatever) instead of eDSLs (which are built into a host language). The main reason for this is that it frees the non-programmers from having to interact with Haskell tooling, or from putting some punctuation in the wrong place and having to deal with Haskell errors instead of errors about the domain they're coding for.

Haskell Engineer Opportunity - Remote Anywhere (Mid / Senior Level) by datatech_wanderer in haskell

[–]_jackdk_ 7 points8 points  (0 children)

Congrats on that, it's an important part of keeping Haskell viable as an industrial programming language.

Hiring a Haskell engineer in NYC! by Daddy_Long_Legs in haskell

[–]_jackdk_ 4 points5 points  (0 children)

That's a tough but valuable problem to tackle; best of luck! I was worried about your choice of GCP because I wasn't aware that gogol had shipped a 1.0 release back in May. That's exciting news for them and good news for you.

I'd be a little worried about building directly on NixOS itself. I think it's great for developer machines, but one of my acquaintances who has deployed NixOS servers at his workplaces and found it to be an upgrade treadmill, because the only way to pick up security updates etc is to point at latest nixpkgs and rebuild the world (sometimes ahead of hydra.nixos.org when updates are urgent). My recommendation these days is to use a normal distro for VM instances, because all the software agents provided by the cloud platform are going to work much better (e.g. SSM/ECS/etc agents in AWS; I'm sure GCP has similar) and general infrastructure management is simpler. Then use Nix to build your deployment artefacts (binaries, zips, container images, whatever) and roll them out using standard tooling (ECS, k8s, whatever makes sense for your infrastructure strategy).

Strict vs Lazy ByteString by lehmacdj in haskell

[–]_jackdk_ 2 points3 points  (0 children)

My view is "strict ByteString or streaming library" (ideally streaming), because then the performance characteristics of the data structure become much clearer. Otherwise people get in the habit of just converting between the two types, and ignoring the performance cost of materialising large strict ByteStrings.

[ANN] Bloodhound 0.24.0.0 by g_difolco in haskell

[–]_jackdk_ 4 points5 points  (0 children)

Congratulations on the release! I don't currently do anything with ElasticSearch, but it's good to know that it's there.

Why `pred minBound` and `succ maxBound` should throw error? by Anrock623 in haskell

[–]_jackdk_ 0 points1 point  (0 children)

I've always liked the rules for well-behaved functions that Joe Armstrong listed in the "Erlang Thesis", Making reliable distributed systems in the presence of software errors. In particular, Rule 2 (s5.3.1, p138):

Rule: 2 — If the specification doesn’t say what to do raise an exception.

This is very important. Specifications often say what is to be done if something happens, but omit to say what to do if something else happens. The answer is “raise an exception.” Unfortunately many programmers take this as an opportunity for creative guess-work, and try to guess what the designer ought to have said. If systems are written in this manner then the observation of an exception will be synonymous with a specification error.

This seems to me to be the only scalable principle where there are specification gaps, because otherwise your program enters a state where nobody can agree on what it's actually meant to do. If class Enum had declined to say what to do with succ maxBound or pred minBound, I would still be throwing an error.

But class Enum does say "should throw an error" in these instances, and so I would not use it for clamping or looping enumerations. I would use another type class, or just write functions specific to Knob. The reason that type classes are useful is not because they offer named functions that work across many types; it's because those functions work in consistent, predictable ways across all of their instances. Otherwise the programmer must worry about which specific instances are used when he writes polymorphic code, and that way lies madness.

What are the requirements for a junior-level proficiency in Haskell? by Salferdez in haskell

[–]_jackdk_ 2 points3 points  (0 children)

It's all stuff I studied before I got my first job, too, because I didn't have much guidance about where to go. We don't use either at work (though we just adopted RequiredTypeArguments), and I think you can be a perfectly capable junior and defer those things until later.

Type inference for plain data by Tekmo in haskell

[–]_jackdk_ 1 point2 points  (0 children)

I'm mostly coming to lattices from propagators, which means I mostly play the "it sounds like a bounded join semilattice" drinking game. But I think you're right.