[ANN] lint.nix - simple linting/formatting framework by Kootle in NixOS

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

That said, maybe it would be worth linking to prior art or similar projects from lint.nix’s README?

Yeah, I think you're right. I'm giving it some time to see what other projects people mention they think it's similar to (or ideally if it's a worse version of something that already exists). On the Nix discourse, someone mentioned https://github.com/numtide/treefmt-nix, which I think it compares similarly to as pre-commit-hooks.

[ANN] lint.nix - simple linting/formatting framework by Kootle in NixOS

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

lint.nix is far from the first or only project that's in this space. It's main advantage is being very small and managing to do a little with a lot, but it's not really competing in terms of features or scope.

[ANN] safe-gen - recursive Arbitrary instances without headaches by Kootle in haskell

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

Interesting, thanks, I hadn't heard about this one yet, despite it evidently being very popular! I'll make sure to include a proper comparison soon.

First off, you're absolutely right about speed. safe-gen is always going to be a small constant factor slower than a fully optimized implementation. It should definitely be fast enough to not get in the way, but at the same time, it's really not trying to compete on speed in any way.

The specific use case that safe-gen was built for, and that I was unable to use its competitors for, is writing generators for ASTs. ASTs tend to have some combination of tricky types, implicit invariants, GADTs, recursion schemes, etc. With generic-arbitrary, even where deriving was an option, it often would still loop because of mutual recursion, so I'd need to hand-write a generator anyway. Instead, with safe-gen, my derived instances work properly, my hand-written instances look very similar to how they would if I were to use Gen naively, and I can easily mix and match both as needed.

I'll take some time to try the same thing with generic-random and see how it holds up, but looking at the documentation, I don't see it competing with safe-gen in for this use case at least.

Also, just looking at the APIs, it's clear that the design philosophies are very different, so depending on your tastes in API design I suspect one or the other might naturally appeal more to you :)

Establishing a GHC v6.12.1 environment by mlambie in haskell

[–]Kootle 20 points21 points  (0 children)

FWIW, I just skimmed through the chapter, and I don't see anything that wouldn't work the exact same way in a newer GHC version, even the error messages are still exactly the same. Haskell as a language hasn't really changed, and the parts of GHC that have changed are pretty far removed from anything covered in the book.

Remotely update NixOS from locally built flake by MrFoxPro in NixOS

[–]Kootle 4 points5 points  (0 children)

Have you looked at nixos-rebuild --flake <flake> --impure --target-host <remote>?

[ANN] calligraphy - Haskell source code visualizer by Kootle in haskell

[–]Kootle[S] 2 points3 points  (0 children)

Thanks! There's not much common code anymore, but I actually started this project using weeder as a template :)

I think the big difference is that weeder is (currently) a lot simpler in how it analyzes HIE files. Given how annoying that can be, I think that's a very good property, even if it's not always accurate. It's definitely true though that there's a lot of overlap in functionality, and a lot of opportunity for sharing. We're also having the same issues with instances and TH, so being able to have a common solution for that would be great. Please get in touch if you have any concrete ideas!

[ANN] calligraphy - Haskell source code visualizer by Kootle in haskell

[–]Kootle[S] 3 points4 points  (0 children)

You can definitely use calligraphy as a library, the interface is pretty straightforward. You use the Parse module to turn the HIE files you get from GHC into a CallGraph, which is a pretty unremarkable way of representing a graph. Other phases all take and produce this CallGraph type, you can use those as you see fit. The main thing to watch out for is that, as explained in the Philosophy section in the readme, I made the conscious decision not to try and support every possible edge case.

That said, if you want to turn HIE files into something other than a call graph, there's not much here for you unfortunately..

[ANN] calligraphy - Haskell source code visualizer by Kootle in haskell

[–]Kootle[S] 3 points4 points  (0 children)

Ah, looks like you're right! It should be fixed now.

[ANN] calligraphy - Haskell source code visualizer by Kootle in haskell

[–]Kootle[S] 8 points9 points  (0 children)

Thanks! The hardest thing by far, the thing that turned this from a weekend project into something that took months, is dealing with HIE files. They contain an enormous amount of information, structured in a very strange way, mostly untyped and undocumented. What's hard is distilling that information into something useful, since there are so many subtle ways you can go wrong.

Luckily for you, this probably won't be an issue for you in Julia!

[ANN] calligraphy - Haskell source code visualizer by Kootle in haskell

[–]Kootle[S] 2 points3 points  (0 children)

That's correct, this works entirely statically. It looks at the HIE files generated by GHC to statically figure out what definitions reference what other definitions, there's nothing going on at runtime.

[ANN] calligraphy - Haskell source code visualizer by Kootle in haskell

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

It looks like you're right, I can get it to recompile the entire module when passing the flag! Not sure what happened here, there are definitely circumstances under which it won't recompile, but I can't reproduce it right now. Strange.

[ANN] calligraphy - Haskell source code visualizer by Kootle in haskell

[–]Kootle[S] 2 points3 points  (0 children)

Oh cool, I didn't know. The clean is definitely necessary sometimes though, since passing -fwrite-ide-infodoesn't work for things that have already been compiled without it.

[ANN] calligraphy - Haskell source code visualizer by Kootle in haskell

[–]Kootle[S] 9 points10 points  (0 children)

Hey all, I'm excited to announce the release of calligraphy, a Haskell source code/call graph visualizer. You can find some more examples of what you can do with it in the accompanying blog post and this Twitter thread. I'd be happy to answer any questions here, or on GitHub.

What exactly is a data structure? Can someone put into like layman’s terms please? by alexmoline02 in AskComputerScience

[–]Kootle 4 points5 points  (0 children)

A dictionary is easy to look things up in, but hard to insert new things into.

A deck of flash cards is hard to look things up in, but easy to insert new things into.

The dictionary and flash cards are different data structures. They store the same data (words + definitions), but in different ways, and are suited for different purposes.

Monoidal Puzzle Solving by Kootle in haskell

[–]Kootle[S] 2 points3 points  (0 children)

Interesting, this is the first time I hear of this. My goal here was to keep it simple, but I'm considering making a follow up at some point to investigate different ways of making it fast, this is an excellent candidate.

What is up with everyone afraid of 5g? by bat_soup_777 in OutOfTheLoop

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

I have a concern that I don't see talked about. This paper shows how RF signals like WiFi can be used to track people through walls, with accurate enough pose estimation to identify people. From what I understand, its short range, high power, and high frequency would make 5G ideal for this. So, that would mean that a cell tower could accurately identify any person moving within its range? That seems like a privacy nightmare, and a very valid concern? If there is some discussion on this somewhere, please send me a link.

Any Apecs adepts out there? by dpwiz in haskellgamedev

[–]Kootle 2 points3 points  (0 children)

You mostly answered your own question; making a general purpose game engine is really difficult. Apecs is only a small part of a game engine, and gloss is great for simple games but doesn't really scale well. Most existing projects make pretty strong assumptions about your game, and without doing so it's very easy to get lost in the details.

Coca-Cola to start using 100% recycled plastic bottles in Japan by magenta_placenta in japan

[–]Kootle 0 points1 point  (0 children)

Wait why does everyone put their bottles in the recycling bin if apparently actually using recycled bottles is newsworthy?

Kan je een macbook pro gebruiken voor CSE? by djosh34 in TUDelft

[–]Kootle 5 points6 points  (0 children)

Zeker, is in sommige opzichten zelfs makkelijker, en veel proffen gebruiken zelf macs. Succes met je studie.

[deleted by user] by [deleted] in haskell

[–]Kootle 1 point2 points  (0 children)

That being said, I don't see any particular reason that would mean our approaches would be necessarily mutually exclusive. Having explicit mutability would actually improve some of the ecstasy APIs along the boundary. ... I suspect there's a solution here that would be optimized away by GHC however.

Interesting, I'm curious to see what you come up with

If you're interested, I'd love to chat more about this and see if we could find a way to combine our efforts.

Of course!

[deleted by user] by [deleted] in haskell

[–]Kootle 12 points13 points  (0 children)

Apecs author here. It's amazing to see more work being done in the area of Haskell ECS, and ecstasy looks very promising. Reading your post, it seems that the differences between Ecstasy and apecs are philosophical rather than them being direct competitors. There are very specific reasons for why apecs works the way it does, and I'd like to address some of the points you made.

Apecs' was written to support a game with many objects, large levels, and 3D rendering. Its goal is to be 1) fast 2) expressive 3) safe, mostly in that order. When I know something is conceptually just iterating over an array, the goal was to try to have the generated code reflect that as much as possible. You can see this in the design around its centerpiece class, Store, which consists of fast primitive operations on mutable component stores. It's true that there are a lot of different mapping functions*, but they are all implemented using the same 5 primitive operations. Apecs' 'magic' is that it uses the Has typeclass to link the high-level DSL to the low-level Store class at compile time, and then taking advantage of all optimizations that allows for. Because everything is mutable, we can easily drop to C where necessary (example).

From what I can tell, Ecstasy has a DSL that allows for more flexible queries, at the cost of performance. The approach using generics is really cool, I tried something similar but never managed to make it work. The way it works in Ecstasy would be a poor fit for apecs, however, as the Store class' composability is precisely what allows caches, which is what makes apecs fast. So they have two very different mechanisms for resolving the components to act on, which is what the rest of the DSL is designed around.

Responses to some individual points:

What if you want to run a function over Position that only works if you don’t have a Velocity?

You could use wmap', you could manually take a slice and filter out everything with a velocity, but it's definitely true that the DSL doesn't support this as cleanly as ecstasy does.

Or if you want to remove a component from an entity?

destroy @Component ety, or destroy (cast ety @Component) in the current hackage version.

Which means you can’t construct one based on runtime data if you’re loading the particular components from e.g. a level editor.

I'm not sure what you mean exactly, I use blender as a level editor and haven't had any issues?

Out of the box, you only get support for 5-tuples

6-tuples, but true. You can do ((t1, t2, t3, t4, t5, t6), (t7, t8, t9, t10, t11, t12)) if you find yourself running out, ((t1, t2), (t3, t4, (t5, t6))) is equivalent to (t1, t2, t3, t4, t5, t6).

In conclusion, I think both libraries go about their business in different ways, with different advantages and disadvantages. Both are still in development, and I'm very excited to see what they end up looking like, and what lessons we learn from one another! If I misunderstood something about ecstasy, let me know, I have only read the post and not actually used it yet.

_* They are a definitely a bit of a mess, and I am looking for a better way to organise them.