Good First Issues in Haskell
Explore curated starter issues in high-scoring Haskell repositories. Every listed issue belongs to a welcoming repository scored by C-Rank™ on PR merge rates, review responsiveness, and first-timer acceptance.
Arm Issue Sniper for fresh Haskell beginner issues
Beginner issues in welcoming S/A-Tier repositories get snatched within 15 minutes. Receive instant alerts on Discord, Telegram, or Email the minute a maintainer opens a new task.
Live Good First Issues (30)
Real-Time Open GitHub IssuesRelated to #1332 i think there could a solution to facilitate the publication of ~content pages base of markdown files. It would use the same kind of rendering use for Readmes or the About page. It would require a title value in the frontmatter and an optional description one. And the goal be to point to a markdown file, define a route that would be it to have a page at the chosen address. It would be useful for the /documentation/ but for any future need of simple content pages in the future. We could even imagine give a folder (and sub-folders) of markdown pages and a chosen path prefix and it would generate automatically all the equivalent routes matching the folder structure and files names (with index.md as the root endpoint of each folder) Im assigning it to you @tchoutri as we discussed this idea just earlier
Motivation There's a SPECIALIZE pragma on replicateA which writes special faster code for it when the internal State monad is used, but users can't access it through normal means. It's also a more general version of iterate. I think it should be exposed. Proposal There should be a method replicateS: replicateS :: Int -> (s -> (s, a)) -> s -> Seq a replicateS n f = execState (replicateA n (State f)) -- 'iterate' would be defined using it. iterate :: Int -> (a -> a) -> a -> Seq a iterate n f = replicateS n (\a -> (f a, a)) -- Rewrite rules could be added. {-# RULES "fmapSeq/replicateS" forall f n m s. fmapSeq f (replicateS n m s) = replicateS n (fmap f . m) s #-} Options There could be a version which uses runState instead of execState, and returns the modified state as well as the sequence.
On the new pipeline, atrace is not implemented on the PTX platform. atrace (& friends) provide tracing like in Debug.Trace, exported from Data.Array.Accelerate.Debug.Trace. In the rewrite of the compiler, they still need to be implemented for the PTX backend. To work on this issue, you need to work on the new pipeline of Accelerate, available via the branch new-pipeline on my fork (https://github.com/ivogabe/accelerate/tree/new-pipeline). Install cbc and clang as command line tools and add them to the PATH. Write an Accelerate program that uses atrace, and run this program on the PTX backend. You will get errors about missing implementations for atrace in certain functions, which should all be addressed for this issue.
I have looked into the necessary updates to ensure the utility packages work with Accelerate 1.4. I have looked only at the packages listed in the Accelerate README. Overview lens-accelerate: works on master branch, needs major version bump due to re-export of Control.Lens (see also tmcdonell/lens-accelerate#1). accelerate-io: works on master branch. Release due to code changes (no API changes): accelerate-io accelerate-io-vector accelerate-io-JuicyPixels accelerate-io-array accelerate-io-bytestring needs release with major version bump (removed equations from type family). Others do not need changes. linear-accelerate needs release (fix in Num instances, already on master). Also need to relax lens upper bound to 6. accelerate-fft: OverloadedStrings language extension required in llvm-cpu codegen, due to change in dependency. Updated in AccelerateHS/accelerate-fft#14. Installation instructions would be nice to have, since it requires FFTW to be installed (for the native backend
containers/containers/src/Data/IntSet/Internal.hs Lines 1164 to 1172 in 0c3b9ee maxView :: IntSet -> Maybe (Key, IntSet) maxView t = case t of Nil -> Nothing Bin p l r | signBranch p -> case go l of (result, l') -> Just (result, binCheckL p l' r) _ -> Just (go t) where go (Bin p l r) = case go r of (result, r') -> (result, binCheckR p l r') go (Tip kx bm) = case highestBitSet bm of bi -> (kx + bi, tip kx (bm .&. complement (bitmapOfSuffix bi))) go Nil = error "maxView Nil" Core: Rec { -- RHS size: {terms: 47, types: 28,
When the new-pipeline got Windows support (ivogabe#13), we disabled the Parlaylib allocator and switched to the system allocator. This was needed as we couldn't link to the functions from Parlaylib. This may have been caused by a mistake in the Cabal configuration. (ivogabe#19). We should test this again. Hopefully we can just remove the compile-time switch between the system allocator and the ParlayLib allocator from the code, and always use ParlayLib. @Doppie23 or @MikevanHuizen2912, if one of you still has Accelerate running on Windows and has some time to test this, it would be greatly appreciated if you could test this! Otherwise @TravisCardwell or I will test this whenever we feel like booting into Windows.
Given a Gren file with a known compilation issue like so: module Broken exposing (..) main = Html.text "Hello" If I compile this module with output to a file, compilation errors are reported to STDERR: $ gren make Broken --output=broken.js --report=json 2> errors.json $ cat errors.json | jq { "type": "compile-errors", "errors": [ { "path": # etc... But if I redirect the output to STDOUT, reporting on STDERR disappears. $ gren make Broken --output=/dev/stdout --report=json 2> errors.json $ cat errors.json # file is empty Gren version 0.6.6 on Linux.
Currently there is no way in SAWScript to construct an Int value that is less than zero. This may or may not have been intentional; however, it's undocumented, unexpected, and not consistent with the name of the type. Rather than rename the type to Nat or UInt or something at great length, we should just lift this restriction. One way is via #3392: currently you can only lift back to Int from Cryptol bitvectors and that mechanism is unsigned-only, but #3392 expands that to Cryptol's Integer type. We don't necessarily need to add SAWScript-level arithmetic, but we should at least allow negative integer literals. That is neither difficult to parse nor difficult to implement. Note that before allowing negative Int values we do need to take steps to avoid exposing them as Cryptol numeric types, which are unsigned. This is being handled in #3392 and #3393.
Summary The // operator gives two different answers for the same operands depending on whether the compiler inlined it: 281474976710656 // 2 --> 0 apply (//) 281474976710656 2 --> 140737488355328 -- correct (apply f a b = f a b, so the second forces the kernel function to run.) The inlined form is generated as (a / b) | 0, which truncates the result to 32 bits. The kernel function _Basics_idiv uses Math.trunc, which is correct at any magnitude. The two have disagreed since Math.trunc was introduced in core in 2023; the code generator was not updated to match. This is not only a precision limit; it is the same expression producing two values depending on syntax. Reproduction module Main exposing (main) import Array import Math import Node import Stream import Task
If you hdb app/Main.hs and app/Main.hs doesn't exist, you get an error message about ghc --numeric-version failing. Instead, we should make sure the target exists before trying to set up and fail with an error message gracefully
In the course of chasing #3343 it became clear that bvEq_refl is missing from basic_ss. This is silly and should be fixed. (There are reasons to not necessarily unfold or rewrite equalities, which is why a lot of the equality-related rules are left out. But those reasons don't extend to reducing reflexivity.)
We use a naïve List.find when normalising categories, which is linear in complexity. We can probably use a Map instead.
We only use blue/red messages when starting the executables, we should vendor those.
Today, iso8601-time is only used for parseISO8601, but we already use iso8601ParseM from the time library elsewhere, so no need for an extra dep.
In the CircuitHub codebase we have: -- | @range \@> now()@: true when the current timestamp falls within the range. currentlyValid :: Expr (Range UTCTime) -> Expr Bool currentlyValid range = rawBinaryOperator "@>" range now we should upstream this or something similar, since this is something we want to quite often do with ranges.
Suppose you have these files: a/a.saw b/b.saw c/c.saw and suppose both b.saw and c.saw do include_once "../a/a.saw", and c.saw also includes b.saw. Then from the perspective of c.saw the path of a.saw is ../a/a.saw, but from the perspective of b.saw the path is ../b/../a/a.saw, because we try to make includes relative to where they're included from. But include_once just looks at the path strings, and they're different, so this doesn't work as intended. This does, however, seem like a reasonable thing to do and to want include_once to work for, so I guess we do need it to normalize paths for comparison... much as normalizing paths is annoying and generally wrong. (That or we could check the system-level file identity... but I'm not sure how you do that from Haskell or whether it's workable in Windows.) @qsctr
Currently, names produced in generated LLVM code are not consistently mangled to ensure they don't clash with one another or with user-written code. We should think through how much mangling is needed for this, and implement it consistently for all generated names in LLVM code.
Summary DateTime (core/core/DateTime.hs) derives ToJSON/FromJSON but has no ToSchema instance. Because Schema's generic derivation requires every field's type to have ToSchema, any record exposed through the web transport — a query read model registered via deriveQuery / withQuery, or any type deriving ToSchema — fails to compile the moment it contains a DateTime (or Maybe DateTime) field. Since DateTime is the natural type for timestamps carried on events and folded onto entities, this makes it impossible to surface a timestamp on an HTTP read model without a workaround (an orphan instance, or converting the field to Int epoch seconds / Text first). Reproduction import Core data Row = Row { id :: Uuid , occurredAt :: DateTime -- or `Maybe DateTime` } deriving (Generic) instance ToSchema Row -- ❌ No instance for `ToSchema DateTime` Maybe DateTime fails the same way — instance ToSchema (Maybe inner) needs ToSchema inner. Expected DateTime should have a ToS
Following the publication of Scarf moving away from Haskell, discussions mentioned that type-family-heavy code, like code using beam, can build slowly. I personally think that the tradeoff for this slower compilation is much, much more safety when interacting with the database. However, if we can preserve this safety and improve build times, we should! This ticket is about creating a benchmark for building a beam-based application. Improvements to build times can follow separately.
Please consider adding hadolint on winget.
MySQL remains a serious choice over Postgres in many domains. We should support it. There exists a beam-mysql, but it is unmaintained. beam-mysql is based on mysql, which is also unmaintained. We should: import beam-mysql in this repo; Switch over to use mysql-haskell, which is maintained I'm a little oversubscribed at the moment, but I'm happy to review pull requests!
The SAWScript typechecker and interpreter are built with -Wno-incomplete-uni-patterns and there's a long comment at the bottom of Typechecker.hs that explains why. Basically, there are a couple places that use irrefutable patterns with incomplete matches as a shortcut. These basically function as assertions that the omitted cases of the partial matches are not reached, which is fine until they are and then it turns out that the generated code throws UserError behind your back. That results in the following undesirable behavior: sawscript> let x = 3 saw-script/src/SAWScript/Typechecker.hs:2216:5-60: Non-exhaustive patterns in [(pat'', e1, s)] sawscript> IOW, it crashes but doesn't exit, and while it does print the Haskell source location, it doesn't print what the offending value was. This is not what we want; the handful of affected cases should be turned into explicit panics that print useful messages. We can afford a couple extra lines of code for that in a project the size of SA
Example: { "type": "package", "platform": "common", "name": "example/package", "license": "BSD-3-Clause", "summary": "this summary line is not that long... but it is longer than expected at 80 chars", "source-directories": [ "src" ], "version": "1.0.0", "exposed-modules": [ "Main" ], "gren-version": "0.6.0 <= v < 0.7.0", "dependencies": { "gren-lang/core": "7.4.0 <= v < 8.0.0" } } "gren make" produces: gren: DecodeProblem "{\"command\":\"make\",\"optimize\":false,\"sourcemap .... <snipped> \"summary\":\"this summary line is not that long... but it is longer than expected at 80 chars\" <snipped> (Field "project-outline" (Field "summary" (Failure (Region (Position 1 266) (Position 1 348)) InvalidInput))) CallStack (from HasCallStack): error, called at terminal/Main.hs:30:13 in gren-0.6.5-inplace-gren:Main HasCallStack backtrace: collectBacktraces, called at libraries/ghc-internal/src/GHC/Internal/Excep
Many stream primitives can probably be rewritten with Selective since they only bind on a case distinction.
Our current default warning and language settings are a bit ridiculous. Lots of things are globally on for no reason, lots of things are globally off for no reason, and there's no reasonable structure to what is on or off. The Cabal file should be organized better, and the defaults should be improved.
When you run saw --help, it returns exit code 2: $ saw --help <snip> $ echo $? 2 This is a bit unfortunate, as I sometimes use saw --help as a basic smoke test to verify if saw can run at all on a given machine, but the non-zero exit code makes scripts believe that saw --help isn't working as expected. Any objections to changing the behavior to return exit code 0 instead?
Context: While inspecting JS bundles served on Flora I was comparing it to the JS of CDN version of AlpineJS (one of the lib currently included in the main js bundle), and it was only 18kB of JS for ~50kB for what's served by Flora. It's because its a compressed version served by the CDN. So in a performance of serving less data as possible to users required to be able to use Flora, that could be a way to improve things. How: Compressed versions could be either: Be compressed on the go by the web server Compressed at build time by the assets pipeline, possibly have compressed and uncompressed versions of each assets for browser that don't handle compressed version(?) and metadata of what's compressed stored in the manifest file for the web server to add the right http headers The first version if possible seems to be the less change-demanding but can be source of server-load when under a lot of traffic The second version require make change to the asset pipeline and and the web serve
Right now it is specialised to lists: concatS :: (Monad m) => StreamT m [a] -> StreamT m a I believe it could be: concatS :: (Monad m, Foldable t) => StreamT m (t a) -> StreamT m a Same for the automaton version.
Top Haskell Repositories with Beginner Issues (20)
Updated Daily via GitHub GraphQLThe Software Analysis Workbench
Implementation of the Hydra Head protocol
The Daml smart contract language
A modern step-through debugger for GHC Haskell
A fast, safe, and intuitive DataFrame library.
A modern package index for the Haskell ecosystem
The Plutus language implementation and tools
Dockerfile linter, validate inline bash, written in Haskell
A programming language supporting most features of both declarative and imperative languages
Haskell to VHDL/Verilog/SystemVerilog compiler
⏩ NeoHaskell is a dialect of Haskell that is focused on newcomer-friendliness and productivity.
Assorted concrete container types
Code used throughout the Cardano eco-system
Typed eDSL for writing UPLC /ˈpluː.tɑːk/
Haskell library for writing Discord bots
A type-safe Haskell SQL library
A static website compiler library in Haskell
Hey! Hey! Can u rel8?
we have democratized the LeetCode tests
Haskell Functional Reactive Programming framework with type-level clocks
How to make your first Haskell open-source pull request
Finding approachable Good First Issues in Haskell allows you to build real-world software engineering experience. Instead of submitting PRs to abandoned repositories, GetMerged verifies maintainer review speeds and first-timer acceptance rates before you write a single line of code.
Select any issue above to claim it directly on GitHub, or click a repository to inspect full maintainer review turnaround metrics and triage guidance!
Get this week's top welcoming repos + fresh Good First Issues for Haskell
Free weekly email, scoped to Haskell. No account needed - confirm once and unsubscribe anytime.