r/haskell

▲ 17 r/haskell

[ANN] hpgsql, a pure Haskell PostgreSQL driver (no libpq)

It’s a pleasure to announce hpgsql, a PostgreSQL driver written in pure Haskell (no libpq), with an API largely inspired by the great postgresql-simple library, but featuring:

  • Usage of PostgreSQL’s binary protocol
  • Query arguments passed via the protocol instead of being escaped into the query string
  • Pipelining
  • Prepared statements
  • Ability to stream query results directly from the socket (not just with cursors)
  • Interruption safety, except for very specific (and documented) edge cases
  • Thread safety, unless specific (and documented) instructions say otherwise
  • A SQL quasiquoter like the one in postgresql-query and hasql-interpolate

Here’s an example of a pipeline mixing streams, prepared and non prepared statements:

f :: Int -> IO (Stream (Of Aeson.Value) IO ())
f val = do
  (updateTbl :: IO (), aggRes :: IO (Only Int), largeResults) <-
    runPipeline conn $
      (,,)
        <$> pipelineExec_ [sql|UPDATE tbl SET val=#{val}|]
        <*> pipeline1 [sql|SELECT SUM(val) FROM tbl|]
        <*> pipelineSWith
          (rowDecoder @(Vector Int, Vector Text))
          -- We use a prepared statement for the query below
          [sqlPrep|SELECT x, y FROM tbl|]
  updateTbl
  Only total <- aggRes
  Streaming.map Aeson.toJSON <$> largeResults

Also, I am maintaining hpgsql-simple-compat, a fork of postgresql-simple that preserves its API as much as I could make it, but with internals rewritten to use hpgsql. The idea is to provide a simpler migration path from postgresql-simple; one that allows a smaller initial changeset and then the possibility of migrating queries to hpgsql one at a time. I have even migrated a CLI tool of mine, codd, as an example.

hpgsql-simple-compat is not in Hackage as I wasn’t sure duplicating the search space with modules, types, and functions already in postgresql-simple would annoy users. It’s in the “hpgsql-simple-compat” folder in the repository.

Some initial benchmarks show hpgsql can materialize rows from a query in ~38% the time postgresql-simple takes, and ~70% the time hasql takes (on my computer, Linux x64, GHC 9.10.3, compiled with -O1). Peak memory usage is trickier to analyze, and I therefore welcome people that know more to read the benchmarks page and help me better understand them. Also, please scrutinize these benchmarks as much as you can.

I want to encourage and welcome contributions, bug reports, questions, suggestions. Nothing’s off the table: what would you want or what do you need from such a library?

I really want to hear from the community, both those eager to switch and potential future users.

reddit.com
u/mzabani — 5 hours ago

AI + Haskell goes hard

I'm not "in" the Haskell community, but I do like FP concepts and respect that Haskell brings a lot of these concepts to the table for other languages to adopt.

I've been heavily using AI in my first Haskell project, and I am finding that, aside from long build times, it's an excellent experience. Not sure why more people are not talking about this. Is it a Haskell culture thing? It's next level good (compared to python + ruff + mypy vibe coded personal projects, I'm fighting bugs a lot less in production)

reddit.com
u/Churrrrmokopuna2540 — 4 days ago
▲ 15 r/haskell

implemented my own splitOn. Feedback needed

Hello everyone,

I'm a beginner looking for feedback. I wrote my own splitOn because words only splits on whitespace, and I didn’t want to pull in the split package just for one small utility function.

I ended up using a State monad approach. I know the state monad is probably overkill here, but I couldn’t think of a more idiomatic Haskell to mutate/build out a new list. I also used Seq to idiomatically access the last item efficiently O(1) instead of List

Please give me feedback on:

  • more idiomatic Haskell style
  • whether State here is considered bad practice
  • other cleaner solution not using State, I initally thought of fold but my brain froze
import Control.Monad.State (State, get, put, runState, execState)
import System.Environment (getEnv)
import Data.Sequence (Seq((:<|), (:|>), Empty), (|>), singleton)
import Data.Foldable (toList)

splitOn :: String -> Char -> [String]
splitOn text delimiter =
    toList $ execState (splitString text) (singleton "")

    where
    splitString :: String -> State (Seq String) ()
    splitString "" = return ()
    splitString (char : tail) = do
        parseChar char
        splitString tail


    parseChar :: Char -> State (Seq String) ()
    parseChar char = do
        currentState <- get
        if char == delimiter then put $ currentState |> ""
        else do
            let (front :|> lastItem) = currentState
                newLastItem = lastItem <> [char]
            put (front :|> newLastItem)

Appreciate any feedback or suggestions.

reddit.com
u/CodeNameGodTri — 4 days ago
▲ 11 r/haskell

Techniques for debugging a runtime infinite loop?

I recently made a series of changes to the inlining / simplification pass for my compiler that ended up resulting in a runtime <<loop>> with certain inputs. (This was for / in another lazy language, but very similar to Haskell, so I thought I'd ask here). I eventually ended up debugging it by making simplification edits to all the areas I had touched, until the infinite-loop disappeared, then looking closely at the one that fixed it. A cut-down example of the bug looks like:

simplify xs = deltaCpx
    where
      (deltaCpx, xs') = mapAccumL insLet 0 xs

      insLet dc x = (dc + deltaCpx, x * 2)    -- OOPS, meant deltaCpx', here!
          where
            cpx'      = if x > 5 then 10 else 0
            deltaCpx' = cpx' - 2

The language I'm working in detects the loop and prints "BLACK HOLE" at runtime, similar to Haskell detecting and printing "<<loop>>", but neither gives any detail on where it was encountered.

So are there some techniques you've used that can help with debugging such problems? Could there be additional language / runtime support to help with this?

EDIT: to clarify, by <<loop>> or BLACK HOLE, I mean the runtime exception generated when attempting to evaluate a thunk that is already currently being evaluated, not an actual infinite-loop that chews up time.

reddit.com
u/AustinVelonaut — 5 days ago

My Newbie Error "Could not deduce ‘RealFrac a’ arising from a use of ‘floor’ from the context: Num a"

Hi, I'm learning Haskell, and I admit I'm just playing with it right now.

While I'm not a terribly experienced programmer, I do have a Bachelor's in Computer Science. My professional experience has been restricted to mostly web development in Typescript sadly.

I have not touched functional programming, but this seems unrelated to functional intricacies and more me having a primitive understanding of number types.

I'm playing with pattern matching and guards so maybe excuse the silly code, I'm just starting.
I try loading (":l haskell_test.hs") my file in GHCi and get the following compile error

"Could not deduce ‘RealFrac a’ arising from a use of ‘floor’ from the context: Num a" . I take in type Num, and floor doesn't like that general of a type, I take it?

-- testing pattern matching and guards
isXFactorOfY :: Num a =&gt; a -&gt; a -&gt; Bool
isXFactorOfY 0 0 = True
isXFactorOfY 0 y = False
isXFactorOfY x 0 = False
isXFactorOfY 1 1 = True
isXFactorOfY 1 y = False
isXFactorOfY x 1 = False
isXFactorOfY x y  | x &gt; y = False
                  | abs(x / y) &gt; floor( abs(x)/abs(y) ) = False
                  | otherwise = True

I've tried replacing Num a with Real a, RealFrac a, and some other things I've seen. But I'm just poking blindly and don't actually understand the exact issue. I'd like some help understanding it explicitly rather than stumbling upon the compile-able code.

I see the reference for floor is here: https://hackage.haskell.org/package/ClassyPrelude-0.1/docs/Prelude-Math.html#v:floor

I guess I'm confused what it want's floor to take in, I figured any number that's an Int or Float would work. But I'm not sure how to define that the way it wants.

Again sorry for the silly code. I am quite rusty and am having a rough time getting back into .... problem solving, and reading APIs and references it seems.
Thank you in advance for any help or direction you give.

The full compile error output is as follows:

ghci&gt; :l haskell_test.hs 
[1 of 2] Compiling Main             ( haskell_test.hs, interpreted )
haskell_test.hs:3:14: error: [GHC-39999]
    • Could not deduce ‘Eq a’ arising from the literal ‘0’
      from the context: Num a
        bound by the type signature for:
                   isXFactorOfY :: forall a. Num a =&gt; a -&gt; a -&gt; Bool
        at haskell_test.hs:2:1-39
      Possible fix:
        add (Eq a) to the context of
          the type signature for:
            isXFactorOfY :: forall a. Num a =&gt; a -&gt; a -&gt; Bool
    • In the pattern: 0
      In an equation for ‘isXFactorOfY’: isXFactorOfY 0 0 = True
  |
3 | isXFactorOfY 0 0 = True
  |              ^

haskell_test.hs:9:29: error: [GHC-39999]
    • Could not deduce ‘Ord a’ arising from a use of ‘&gt;’
      from the context: Num a
        bound by the type signature for:
                   isXFactorOfY :: forall a. Num a =&gt; a -&gt; a -&gt; Bool
        at haskell_test.hs:2:1-39
      Possible fix:
        add (Ord a) to the context of
          the type signature for:
            isXFactorOfY :: forall a. Num a =&gt; a -&gt; a -&gt; Bool
    • In the expression: x &gt; y
      In a stmt of a pattern guard for
                     an equation for ‘isXFactorOfY’:
        x &gt; y
      In an equation for ‘isXFactorOfY’:
          isXFactorOfY x y
            | x &gt; y = False
            | abs (x / y) &gt; floor (abs (x) / abs (y)) = False
            | otherwise = True
  |
9 | isXFactorOfY x y        | x &gt; y = False
  |                             ^

haskell_test.hs:10:33: error: [GHC-39999]
    • Could not deduce ‘Fractional a’ arising from a use of ‘/’
      from the context: Num a
        bound by the type signature for:
                   isXFactorOfY :: forall a. Num a =&gt; a -&gt; a -&gt; Bool
        at haskell_test.hs:2:1-39
      Possible fix:
        add (Fractional a) to the context of
          the type signature for:
            isXFactorOfY :: forall a. Num a =&gt; a -&gt; a -&gt; Bool
    • In the first argument of ‘abs’, namely ‘(x / y)’
      In the first argument of ‘(&gt;)’, namely ‘abs (x / y)’
      In the expression: abs (x / y) &gt; floor (abs (x) / abs (y))
   |
10 |                         | abs(x / y) &gt; floor( abs(x)/abs(y) ) = False
   |                                 ^

haskell_test.hs:10:40: error: [GHC-39999]
    • Could not deduce ‘RealFrac a’ arising from a use of ‘floor’
      from the context: Num a
        bound by the type signature for:
                   isXFactorOfY :: forall a. Num a =&gt; a -&gt; a -&gt; Bool
        at haskell_test.hs:2:1-39
      Possible fix:
        add (RealFrac a) to the context of
          the type signature for:
            isXFactorOfY :: forall a. Num a =&gt; a -&gt; a -&gt; Bool
    • In the second argument of ‘(&gt;)’, namely
        ‘floor (abs (x) / abs (y))’
      In the expression: abs (x / y) &gt; floor (abs (x) / abs (y))
      In a stmt of a pattern guard for
                     an equation for ‘isXFactorOfY’:
        abs (x / y) &gt; floor (abs (x) / abs (y))
   |
10 |                         | abs(x / y) &gt; floor( abs(x)/abs(y) ) = False
   |                                        ^^^^^

Failed, unloaded all modules.
reddit.com
u/SleepyGuyy — 1 day ago
▲ 68 r/haskell

A Game Boy and Game Boy Color Emulator in Haskell

Hi everyone,

I've made an early version of a Nintendo Game Boy and Game Boy Color emulator in Haskell. It's mostly implemented in Haskell and consists of a core (backend) and two frontends (web via WebAssembly and desktop via SDL2).

The emulator is far from finished (especially when it comes to being optimized for performance), but it boots games with decent compatibility at the moment.

In any case, if you're interested in knowing more about the project, you can check out its GitHub repo here: https://github.com/pixel-clover/ocelot

BTW, the web version of the emulator (which allows you to play ROMs without installing anything on your computer) can be accessed here: https://pixel-clover.github.io/ocelot/

u/Real_Dragonfruit5048 — 5 days ago
▲ 62 r/haskell+1 crossposts

Hi, it's me again, and Converge is hiring for a senior software engineer to join our team. You can find the job description here and can also apply via that link (which is better than messaging me on reddit).

  1. Small engineering team working on decarbonisation and efficiency for the construction industry.
  2. The team does a mix of hardware, software, and applied data science. You'll be joining one of our early-stage product teams (either a very new product or a fairly new product).
  3. We're looking for people with functional programming backgrounds, if it's not production Haskell, it might still be worth talking, but we do need you to have a lot of experience in the functional paradigm.
  4. You won't just be doing Haskell, there's still typescript and python to maintain -- by all means have a lot of enthusiasm for Haskell, but we are here to create products for our customers and users at the end of the day, and we need to do what it takes to do that.
  5. Prefer London/UK, but will consider nearby timezones.
  6. Needs lots of real-world experience on complex products, this is a senior role in a small team, so you'll get lots of ownership and autonomy, but it takes a level of experience to navigate the uncertainty which comes with building in this environment.

Salary range is £90-100K + stock options.

Feel free to ask me questions (I'm cofounder and CTO).

reddit.com
u/gtf21 — 6 days ago
▲ 27 r/haskell

Haskell Tools in Neovim. Autocomplete type signatures?

I am using Neovim with HLS and the Haskell-Tools plugins.

When typing, the plugin automatically inserts the type signature visually, but it is not actually included in the text of the document.

Is there a command that accepts the type signature and inserts into the file?

reddit.com
u/man-vs-spider — 4 days ago
▲ 39 r/haskell

Hi there!

So I am a software developer for decent time now, I also am interested in/enthusiastic about FP. I noticed quite weird divergence between the worlds of software development in general and functional programming.
Namely it seems there is little cross-over between them.

Looking for FP jobs on general IT/software job boards yields almost none.
Yet there is plenty of internet activity (ie. tutorials, explanations, articles, conference talks etc), of bona fide FP/Haskell developers. Hence I imagine there is an industry around that.

I would love to work in FP, but seem unable to even perceive potential opportunities there...

Thanks in advance to anyone sharing their experience with that.

Cheers!

reddit.com
u/Ludonardis — 14 days ago

To go around the ABI error I run haskell server: haskell-language-server-9.6.7~2.13.0.0

and get this message

Message:

Loading the module

'/home/jacekp/Programming/Haskell/cabal-experiments/graphviz-simple/dist-newstyle/build/x86_64-linux/ghc-9.6.7/graphviz-simple-0.1.0.0/build/autogen/PackageInfo_graphviz_simple.hs'

failed.

It may not be listed in your .cabal file!

Perhaps you need to add `PackageInfo_graphviz_simple` to other-modules or exposed-modules.

For more information, visit:

https://cabal.readthedocs.io/en/3.4/developing-packages.html#modules-included-in-the-package

"/home/jacekp/Programming/Haskell/cabal-experiments/graphviz-simple/app/Main.hs" - Cabal

reddit.com
u/Exact_Ordinary_9887 — 7 days ago
▲ 23 r/haskell

Hello Haskellers,

I've built an MCP server that lets AI agents use Hackage. The MCP server is entirely written in Haskell.

It lets LLMs:

  1. perform Hoogle searches.
  2. List package modules
  3. Scrape module documentation in LLM-friendly Markdown.

Why this tool?

I've often seen premium coding agents using outdated functions or not being aware of the latest packages. This MCP lets LLMs access the latest Haskell documentation.

Feel free to contribute or provide feedback.

Check out the GitHub link: https://github.com/tusharad/hackage-doc-mcp

reddit.com
u/Worldly_Dish_48 — 7 days ago
▲ 11 r/haskell

can compile the project with cabal build,

https://github.com/bigos/cabal-experiments/blob/321c37ffa33b1b25e883de39ddc944c5314c5c7c/graphviz-simple/app/Main.hs#L1

but when I load the file in Emacs and use the menu option Haskell/Load tidy core I get an error like this and 5 more that make no sense. What is the meaning of:

Use -v (or `:set -v` in ghci) to see a list of the files searched for.

?

How can I fix the error? It seems that a fix for the problem will provide more help with modules.

/home/jacek/Programming/Haskell/cabal-experiments/graphviz-simple/app/Main.hs:7:1: error:
    Could not find module ‘Data.GraphViz.Attributes’
    Use -v (or `:set -v` in ghci) to see a list of the files searched for.
  |
7 | import Data.GraphViz.Attributes (color, filled, shape, style, textLabel)
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
u/ruby_object — 7 days ago
▲ 34 r/haskell+1 crossposts

I've been working on a small reflective language called Blue, inspired by Kenichi Asai's Black. Blue is built in Haskell, and the reflection mechanism is straightforward: an em operator that lifts a Blue expression into Haskell and evaluates it through the host:

baseEval (EM e) = metaEval e

metaEval :: Expr -&gt; Eval Value
metaEval e = Eval $ lift $ interpret
    ("toValue (" ++ toHaskell e ++ ")") (as :: Value)

em pretty-prints the AST, hands it to hint, and lifts the result back into a Blue Value. Right now em only handles the same forms baseEval handles, so for the moment it's close to an expensive identity function:

BLUE&gt; em 2 + 3
5
BLUE&gt; em if true then 100 else 0
100

The point of having the mechanism in place first is that Value and toHaskell are the bottleneck, not the host. Once I extend Value with cases for lists, lambdas, or floats thenem immediately reaches whatever in Haskell produces those types, without changing the evaluator. So the next steps are extending the value domain rather than touching reflection itself.

A few things I haven't worked out:

I don't know the literature for reflection-via-host-eval specifically. Smith's 3-Lisp and Black expose the evaluator itself rather than delegating to the host. Pointers welcome.

hint is heavy. It's fine while reflection is rare, but if em becomes load-bearing this probably wants to be staged compilation via Template Haskell. Curious whether anyone has built something analogous that way.

Once a program crosses through em, the host can return whatever it likes; I'm informally trusting the result is a well-formed Value. There's probably a clean framing in terms of contracts but I haven't written it down.

Repo: https://github.com/ih1d/blue

reddit.com
u/AdOdd5690 — 8 days ago
▲ 13 r/haskell

Been a minute since I hosted a stream as I've been on vacation. Most recently, we were streaming Saturday mornings but will now be doing every Wednesday at 5 pm in the hopes this will work better for anyone in whichever timezone who'd like to watch.

We've done a number of very focused sessions however I just want this session to be a really fun one so we are going back to Servant, the first library I learned about in haskell and we are going to build a simple authenticated CRUD API to store and retrieve nicknames.

The core focus of our sessions are how to interact with the haskell ecosystem as it is a truly unique language with respect to documentation, both by having little traditional documentation style but also by being a self documenting language and all that means for getting shit done with haskell as a real world language. We also really seek to cater to our audience so if you have questions about Servant or haskell in general, please consider the stream a help session.

We do try to naturally progress the stream to being a more thorough implementation by the end so that if time permits, we will attempt to swap Servant into my Jenga framework.

Link: https://www.twitch.tv/typifyprogramming

u/_lazyLambda — 7 days ago