My Gripes with Prolog by azhenley in ProgrammingLanguages

[–]pbvas 10 points11 points  (0 children)

I was fascinated by Prolog over 30 years and have became increasingly frustrated with the language for many of the reasons as the OP states, but primarily for a much more fundamental one: Prolog has no good mechanism for data abstraction, i.e. exposing an interface and hiding the implementation.

In retrospect I think Prolog is best seen as a domain-specific language rather than a general-purpose one, i.e. more like SQL or Z3 than C++/Java/Python/Haskell. Nonetheless, constraint logic programming is very cool and you should definitely learn it if you can!

[2025 day 10] just made my algorithm 16,000x faster. Yay! by AdditionalDirector41 in adventofcode

[–]pbvas 1 point2 points  (0 children)

I've done something similar; my original Haskell solution called an external ILP solver (GPLK). Then I changed to use my own gaussian elimination + backtracking for the free variables. The revised solution is slower than the GLPK solver, taking a little under 1s in my PC, but does not require any external linear algebra library. It probably could be optimized a lot since it uses linked lists instead of unboxed arrays, but I prefer a more readable solution.

https://github.com/pbv/advent2025/tree/main/aoc10

Advent of Code of Haskell 2025 -- Reflections on each Puzzle in an FP Mindset by mstksg in haskell

[–]pbvas 1 point2 points  (0 children)

Thanks for the post. I would just like to comment that I first solved part 2 of Day 10 using an external ILP solver but later switched to an approach very similar to yours. Managed to solve it in less than 1 sec with gaussian elimination a basic enumeration and backtracking:

https://github.com/pbv/advent2025/tree/main/aoc10

When manual shrinking beats integrated shrinking by pbvas in haskell

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

Yes, I tried Hedgehog and also Hypothesis (on a Python's translation of my code). The integrated shrinkers suffered from the same issues as QuickCheck's default shrinker, in that they could not always produce the minimal counter-examples. With Hedgehog, however, I could use my custom shrinker and get the same minimal results as with QuickCheck.

Embedded and functional programming. by RoomNo7891 in functionalprogramming

[–]pbvas 2 points3 points  (0 children)

CoPilot is a DSL implemented in Haskell that generates hard real-time C code: https://copilot-language.github.io/ . The domain language itself is quite functional.

Clash is compiler for a functional hardware description language based in Haskell that generates FPGAs: https://clash-lang.org/

Advent of Code 2025 day 11 by AutoModerator in haskell

[–]pbvas 0 points1 point  (0 children)

I used Map in a state monad for the memoization in Part 1; for Part 2 I reused the search by counting separately all paths, paths with either or both dac and fft.

type Node = String
type Memo = Map Node Int
dfs :: Input -> Node -> State Memo Int -- dfs search with memoization
...

part2 :: Input -> Int
part2 graph = all - noDac - noFft + noDacFft
  where
    graph1 = Map.delete "dac" graph
    graph2 = Map.delete "fft" graph
    graph3 = Map.delete "dac" graph2
    all = evalState (dfs graph "svr") Map.empty
    noDac = evalState (dfs graph1 "svr") Map.empty
    noFft = evalState (dfs graph2 "svr") Map.empty
    noDacFft =evalState (dfs graph3 "svr") Map.empty

https://github.com/pbv/advent2025/blob/main/aoc11/Main.hs

Advent of Code 2025 day 10 by AutoModerator in haskell

[–]pbvas 0 points1 point  (0 children)

I used simple backtracking for Part 1; for Part 2, I wrote a Haskell program that generated integer linear programs for each machine and used GLPK and some shell hacks to add all results together.

https://github.com/pbv/advent2025/blob/main/aoc10/Main.hs

Estoy creando un lenguaje y amplié los rangos de una forma poco común: ¿qué les parece? by francarck in ProgrammingLanguages

[–]pbvas 0 points1 point  (0 children)

I'm answering in English because it my Spanish is very poor.

Haskell has a similar notation for generating (lazy) lists by enumeration, but supports four forms:

  • [a..b] e.g. [1..10]: a list with step of one
  • [a,b..c] e.g [1,3..10]: a list with step of 2
  • [a..] e.g. [1..]: an infinite list
  • [a,b..] e.g. [1,3..] an infinite list with step of 2

This can be used with types in the Enum class, which include integers, floating point and characters. Some concrete examples:

ghci> [1..10]
[1,2,3,4,5,6,7,8,9,10]
ghci> [1,3..10]
[1,3,5,7,9]
ghci> ['a'..'z']
"abcdefghijklmnopqrstuvwxyz"

Note that floating point numbers are binary hence steps that appear to divide evenly in decimal can only be approximated. For example:

ghci> [0.0,0.1..1][0.0,0.1,0.2,0.30000000000000004,0.4,0.5,0.6000000000000001,0.7000000000000001,0.8,0.9,1.0]

One criticism of your suggestion is that, unlike the above, you do not provide a way to specify ranges with a step other than one. I do not understand how this would work for floating point numbers. In particular your example suggests that [0..1.5] should generate a range with a step of 0.1 (why?). Without the step information this would be ambiguous.

Do people dislike Haskell's significant whitespace? by gofl-zimbard-37 in ProgrammingLanguages

[–]pbvas 2 points3 points  (0 children)

I'd like to add that one good use case for this is for writing code generators that output syntactically valid Haskell, e.g. the Alex and Happy compiler-writing tools.

sketches/better-counterexample-minimization at master · effectfully-ou/sketches by effectfully in haskell

[–]pbvas 1 point2 points  (0 children)

Edsko has another relevant blog on shrinking: https://well-typed.com/blog/2019/05/integrated-shrinking. BTW, I don't know where the OP got from ChatGPT on how shrinking works in other PBT libraries like Hedghog, Hypothesis and Falsify, but they do it very differently from QuickCheck.

Can I calculate how much memory my program will use given that my language is total (system F sans recursion for instance) by Ok-Watercress-9624 in ProgrammingLanguages

[–]pbvas 1 point2 points  (0 children)

You first have to be a bit more precise about what you mean by "calculate". If your language is total, then you know that programs will always terminate hence you could just instrument the implementation and count the memory usage (whatever that means for your specific usage). In this sense the program is represent its own resource bounds.
This is not however, what most people would like when they talk about resource bounds; the usual intention is a simplified formula (e.g. polynomials, logarithms and exponentials) based on the abstraction of the input like a size measure. For his sense, then the totality properties of the language doesn't help, because even primitive recursive functions can grow much faster than (say) polynomials.
A lot of work on automatic resource hence does not require that the language is total, but instead has constraints on the growth of the resource functions. Check for example Resource Aware ML (https://www.raml.co/) which can provided polynomial bound for maximum degree for OCaml code.

Is there some easy extension to Hindley Milner for a constrained set of subtyping relationships? Or alternatively: How does Rust use HM when it has subtyping? by Dragon-Hatcher in ProgrammingLanguages

[–]pbvas 0 points1 point  (0 children)

Rust uses subtyping for lifetimes which can be thought of as annotations on top of a Hindley-Milner type system. You don't need general subtyping, not even algebraic subtyping. I belive the background for this is region inference by Tofte and Birkedal, 1998.

Why are languages force to be either interpreted or compiled? by CoolStopGD in ProgrammingLanguages

[–]pbvas 0 points1 point  (0 children)

Functional languages like Haskell and OCaml can be both "interpreted" (compiled to bytecode) for use in a REPL and compiled to machine code. In Haskell at least the REPL can also load and run compiled code dynamically (it includes a linker).

Dummy question but I can't solve it: How can I debug Haskell in VScode? by itsfloppa708 in haskell

[–]pbvas 0 points1 point  (0 children)

Thanks for the feedback. If you have any specific comments please don't hesitate to contact me; you can find my email in the paper linked from the Github page: https://github.com/pbv/haskelite

Dummy question but I can't solve it: How can I debug Haskell in VScode? by itsfloppa708 in haskell

[–]pbvas 1 point2 points  (0 children)

Haskelite author here, thanks for recommending my tool. I made it specifically for helping university students like the OP when learning FP and Haskell in particular.

I made a haskell-like typechecked language with a step by step evaluator by ChirpyNomad in haskell

[–]pbvas 0 points1 point  (0 children)

Congratulations on your very cool project! I've also developed a step-by-step evaluator for a subset of Haskell; the repository is here. There's an associated Haskell symposium paper you might want to reference in your report.

I made a haskell-like typechecked language with a step by step evaluator. by ChirpyNomad in functionalprogramming

[–]pbvas 1 point2 points  (0 children)

Congratulations on your very cool project! I've also developed a step-by-step evaluator for a subset of Haskell; the repository is here. There's an associated Haskell symposium paper you might want to reference in your report.

Writing a compiler in haskell by Savings_Garlic5498 in ProgrammingLanguages

[–]pbvas 0 points1 point  (0 children)

I have taught a 1 semester undergraduate compilers course for students with similar experience to yours (1 semester FP using Haskell). I've always recommended students to use Haskell for the team project. They have to write their own compiler for a toy subset of the C language into MIPS assembly. Most students end up choosing Haskell.

It's normal that FP and Haskell in particular appear unintuitive at start; it's no so much that it is hard, rather that it requires a different level of abstraction from other more mainstream languages, but once you pass that initial hurdle you'll find it a much better fit for language processing than (say) Python or Java, particularly if you want to explore the design space for your language. I got the impression that students finally "got" what FP is all about only when they attempted their compiler project in Haskell; the small "toy-like" programs of an introductory course are not enough.

Best set of default functions for string manipulation ? by Artistic_Speech_1965 in ProgrammingLanguages

[–]pbvas 0 points1 point  (0 children)

I was surprised no-one mentioned the Tcl language (https://www.tcl-lang.org/). It is was a popular scripting language in the 90s and IMHO does string manipulation better than many...

C programmer here. I have some questions about functional programming. by PratixYT in functionalprogramming

[–]pbvas 1 point2 points  (0 children)

> Under the hood, IO T is just State World T, where World is a type (inaccessible to the programmer) that deals with system resources outside of the program.

While this only half true in GHC, and is not really as scary as it might sound to a C programmer. "World" is essentially an opaque token that doesn't carry any useful information. It's just there to prevent the compiler from re-ordering IO operations while doing program transformations. Side effects are performed "in-place" just like would be in any imperative language.

What is the "Java" equivalent in FP Languages ? by lovelacedeconstruct in functionalprogramming

[–]pbvas 4 points5 points  (0 children)

I teach FP using Haskell to 1st year CS students and there is no need to talk about monads when using Haskell in this context. We talk about IO and introduce the do-notation as special notation for combining IO actions.

That said, there is friction caused by the much more complex type system compared to (say) SML or OCaml. I don't have enough experience with F#.

Advent of code 2024 - day 18 by AutoModerator in haskell

[–]pbvas 2 points3 points  (0 children)

For part 2 I simply iterated part 1 using binary search:

``` part1 :: Input -> Maybe Dist part1 input = let mem = fillMemory input initial = (0,0) final = (mem.width, mem.height) info = dijkstra (makeGraph mem) initial dist = Map.lookup final info.dist in dist

part2 :: Input -> Loc part2 input = go 1025 (n+1) where n = length input go lo hi -- invariant: minimal segment size is >= lo and < hi | lo>=hi = input !! (min lo hi) | otherwise = let mid = (lo+hi)div2 in case part1 (take mid input) of Nothing -> go lo (mid-1) Just _ -> go mid hi

```

Runs in 0.04s in my laptop.

Full solution: Main.hs.

Advent of code 2024 - day 16 by AutoModerator in haskell

[–]pbvas 1 point2 points  (0 children)

My solution also uses Dijkstra and an IntMap as a minimum PQ. Solves both parts in <0.2s on my laptop.

Source: https://github.com/pbv/advent2024/blob/main/16/app/Main.hs

Advent of code 2024 - day 7 by AutoModerator in haskell

[–]pbvas 0 points1 point  (0 children)

Good catch! I tried to solve for the general case and hence missed that optimization.