Hacker Newsnew | past | comments | ask | show | jobs | submit | one-punch's commentslogin

You have implemented a form of ‘ad-hoc polymorphism’.

This is different from ‘parametric polymorphism’, which is what people call generics.


I somewhat disagree. FTA: “If the callsite is some_function(2);, the compiler resolves T as i32 and selects the corresponding branch, returning the value incremented by one. […] The important point is that the decision is driven entirely by type information, not by runtime inspection”

Given that, this isn’t that different from C generics (https://en.cppreference.com/w/c/language/generic.html), and people call that generics, too.

Having said that, even ignoring that this requires all implementations to be in a single source file (yes, you probably could use m4 or #include or whatever it’s called in this language) I do not find this syntax elegant.

Also, one thing that it doesn’t seem to support is generating compiler errors when calling a function with a type that isn’t supported.


The key concept in "parametric polymorphism", which is what programming language nerds mean by generics, is "parametricity" [1]. This is basically the idea that all calls to a generic function should act in the same way regardless of the type of the actual concrete calls. The very first example breaks parametricity, as it multiplies for float, adds for i32, and isn't defined for other types.

It's implementation has the same issues as generics in Zig, which is also not parametric.

It's ok to explore other points in the design space, but the language designer should be aware of what they're doing and the tradeoffs involved. In the case of adhoc (non-parametric) polymorphism, there is a lot of work on type classes to draw on.

[1]: https://en.wikipedia.org/wiki/Parametricity


I don’t see how that Wikipedia page supports your claim “The key concept in "parametric polymorphism", which is what programming language nerds mean by generics, is "parametricity"”. That page doesn’t even contain the character sequence “generic”.

IMO, https://en.wikipedia.org/wiki/Generic_programming is more appropriate. It talks of “data types to-be-specified-later”, something that this and C generic lack. That’s one of the reasons that I wrote “I _somewhat_ disagree”.

Also, I don’t see how one would define “act in the same way”. A function that fully acts in the same way regardless of the types of its arguments cannot do much with its arguments.

For example, a function “/” doesn’t act in exactly the same way on floats and integers in many languages (5.0/2.0 may return 2,5 while 5/2 returns 2; if you say it should return 2,5 instead you’re having a function from T×T to T for floats but a function from T×T to U for ints; why would you call that “act in the same way”?), “+” may or may not wrap around depending on actual type, etc.


Right, but C-style generics really are not generics at all. As other comments point out, they effectively are conpile-time if statements. A generic function would automatically instantiate and generate required code for different call types, and perform the correct operations. The C-style "generics" are a conpile-time switch statement, switching on types.


For context, see the recent HN discussion on “The Expression Problem and its solutions”:

https://news.ycombinator.com/item?id=45155877


You might be interested in nickel (https://nickel-lang.org/), which is a modern take on configuration management based on the experience of Nix/NixOS configurations: purely functional configuration, built-in validation (types & contracts), reusable (functions, modules, defaults), and in addition exports to Yaml, Json, etc.

To integrate nickel with nix, see how organist (https://github.com/nickel-lang/organist) does DevShell management.


lix [1] might be less affected. Pierre Bourdon noticed that lix refactored surrounding code 4 months ago [2], and a comment claims that this Lix commit at least patched a different vulnerability GHSA-wf4c-57rh-9pjg [3].

To use lix instead of nix, set `nix.package = pkgs.lix` in your NixOS/home-manager configurations.

[1]: https://lix.systems/

[2]: https://mastodon.delroth.net/@delroth/113110218127456491

[3]: https://lobste.rs/s/ixb3v7/nix_2_24_is_vulnerable_remote_pri...


What's the difference between Nix and Lix? The website is still not entirely clear.

I mean as an user, why would I want to use it (besides avoiding this vulnerability)


Lix is a (nixpkgs-compatible) fork of Nix, led by Nix community members that don't get along with the core Nix team.

At this point, the primary reason to switch to Lix would be if you trusted the Lix folks more than the core Nix team


There are plenty of fantastic reasons not to, despite the prior issues with Eelco's leadership style. The NixOS Starknet situation[1] was very suspicious and involved many of the wrong incentives for an open source project. One of the primary people involved was trying to get the drops transferred to other people's accounts (getting around geofencing prohibiting US withdrawals too). So it is virtually guaranteed that is being transferred toward something other than the NixOS binary cache despite it being emphasised it would go there. I guess it will be going to "save Nix together" for the fork. All €20 000 or what-not of it.

At least Lix is doing some interesting things with the language and fixing some long-standing regressions, but some of the people involved seem to enjoy standing next to others doing the work whilst they loudly take credit, and participating in cryptocurrency ponzi schemes using open source as the vessel.

[1] https://discourse.nixos.org/t/starknet-cryptocurrency-contri...


Lix claims to have a more welcoming community, but I too often see prominent members gloating about every Nix bugs and implementation details on Mastodon and elsewhere so YMMV.


More welcoming how, by stabbing the heart of Eelco with shitty demands? Very welcoming.


If you look elsewhere in this thread, many of the bullies are doing PR for Lix and trying to use this situation to their advantage. What no one is disclosing to people is that their fork of nixpkgs (ForkOS) is nearly done, so pointing people to it is going to be almost entirely in their benefit. But, why would sociopaths tell people that when they can just publicly embarrass people instead?

The amount of gaslighting here is frankly astounding. There were some good developers who went over to Lix but also a few pathological liars and primary school bullies. People don't know half of the abuse going on.


Didn't get along is an understatement. They gaslit and destroyed the little bit of leadership structure of NixOS had through harassment and bullying.


I think you are referring to 4 out of 5 NixOS board members quitting

https://old.reddit.com/r/NixOS/comments/1dqn9os/4_out_of_5_n...


Watch out, they may call you the problem when they're accidentally talking about themselves...

It's very bad and one can simply look through the Discourse and GitHub issues from earlier this year to discover the full extent of the problem. Watch how they turn a security issue into PR now, this is just a microcosm of the dishonesty.


[flagged]


I have not been following closely this back story, so I am not aware of such ban, or that (allegedly) Lix is Pierre Bourdon’s software.

I am not affiliated with Nix (Cppnix) or Lix.


>I have not been following closely this back story, so I am not aware of such ban

https://news.ycombinator.com/item?id=41503923


Why call it "Cppnix"?


It helps disambiguate Nixlang from the codebase that includes the Nix CLI and the Nix daemon, for one. It's also an unambiguous designation for the original Nix implementation, as opposed to Lix and Tvix.

A Lix user might well reasonably say they 'use Nix' because they use Nixlang. Thus some people are Nix users but not CppNix users. As Tvix matures, the same will be true of Tvix users.


Because apparently nix isn’t enough despite being the project name, executable name, and the name of the language it implements. No one calls rust “rustrust”


Because it's written in C++ and the fork plans to rewrite in Rust?


Also there's too many things called Nix.

There's the overall project, the language, and the primary interpretation. It's also why you'll sometimes see nixlang to refer to the language.


Thought was the norm using capitalized for language and lower case for the tooling. So Nix/nix, like AWK/awk and Go/go.


Full caps AWK feels like a relic from the screaming UNIX days, and golang for Go is incredibly common (and as far as I can tell, the proximate cause of the nixlang term)


Then there is also golang


> fork plans to rewrite in Rust

Lmao. Won't ever happen.



oh?


using "yikes" outside of reddit to concern troll is bad manners.

i appreciate sharing alternative forks that fix problems.


Tone policing outside of Mastodon to concern troll is bad manners.

I don't appreciate tankies sharing their nonsense after getting kicked out of a community.


Do you have examples where Python’s Hypothesis (and its shrinking) works better than Haskell’s QuickCheck? This would let us improve Haskell’s QuickCheck.

My understanding is that Haskell’s QuickCheck can shrink functions, and with parametric polymorphism, can work with vector types and more [1], which would be difficult if not impossible in Python.

And in general, the base types covered by the shrinking in Python’s Hypothesis should have analogues by the shrinking in Haskell’s QuickCheck. And with deriving, Haskell’s QuickCheck should get shrinking ‘for free’ as in Python’s Hypothesis.

Also, Haskell’s QuickCheck extends to stateful and parallel checking, which is not supported in Python [2].

[1]: https://library.mlabs.city/mastering-quickcheck "Mastering QuickCheck: Advanced yet Practical Techniques for Property-Based Testing"

[2]: https://stevana.github.io/the_sad_state_of_property-based_te... "The sad state of property-based testing libraries: A survey of property-based testing libraries"


I have to admit the last time I seriously worked with QuickCheck was quite a while ago.

> My understanding is that Haskell’s QuickCheck can shrink functions [...]

Are you talking about shrinking a value of type (a -> b) (for some concrete a and b)? In Hypothesis, if you write a generator that spits out functions, you get a shrinker for free. So that shrinker will shrink functions.

As far as I can tell, QuickCheck's shrinking is based on values. I just checked, the type is still `shrink :: a -> [a]`, so that can't have changed.

In Hypothesis shrinking is based on the generation process. In Hypothesis generators act a bit like 'Functors' in Haskell, ie you can map over them. (You can also filter and `<>` and do monadic binds etc.)

So in Hypothesis you can take a generator that produces integers, and create one that produces only even numbers by (in Haskell terms) mapping (2) over it. Now, the shrinker you get for free will also only produce even numbers.

That's not possible (or at least not easily possible) in Haskell. You would have to define at least a newtype wrapper.

Have a look at https://hypothesis.works/articles/compositional-shrinking/ and https://hypothesis.works/articles/integrated-shrinking/ for some more write-up, especially about how Hypothesis can preserve information even when shrinking past a monadic bind.

If you follow some links in the two articles above, you land at https://github.com/icicle-lang/disorder.hs-ambiata/tree/mast... which is a Haskell library that shares a few design decisions with Hypothesis.

Apart from shrinking, Haskell's QuickCheck can also learn a lot from Hypothesis in terms of floating point number generation. The last time I used QuickCheck seriously, they basically generated floats by converting from a sort-of uniformly sampled fractional number. I see that this commit https://github.com/nick8325/quickcheck/commit/07942642d7987b... seems to have made float generation a lot smarter!

Hypothesis is especially 'nasty' when it generates floats. It has a good chunk of probability allocated to things like various NaNs, infinities, sub-normal numbers, zero, one float past zero, etc, plus of course some probability mass on uniformly chosen floats. See https://hypothesis.readthedocs.io/en/latest/data.html#hypoth... for the docs, but you should check out the code, too.


> In Hypothesis shrinking is based on the generation process. In Hypothesis generators act a bit like 'Functors' in Haskell, ie you can map over them. (You can also filter and `<>` and do monadic binds etc.)

You are right that the generators in Hypothesis correspond to `Functor`s, so you can map over it. Indeed, in QuickCheck, its `Gen` [1] (type of `arbitrary` [2], the generator in QuickCheck) is a `Functor`, and moreover a `Monad`, so you can do monadic binds on `Gen`.

> So in Hypothesis you can take a generator that produces integers, and create one that produces only even numbers by (in Haskell terms) mapping (2) over it. Now, the shrinker you get for free will also only produce even numbers.

> That's not possible (or at least not easily possible) in Haskell. You would have to define at least a newtype wrapper.

Since `Gen` in QuickCheck is a `Functor`, to multiply its output by 2 to generate only even numbers, you can do this in Haskell as:

    fmap (\x -> x*2) (arbitrary @Int)
Or, for those preferring OOP-style chaining:

    arbitrary @Int <&> (*2)
where `<&>` is `fmap` with arguments flipped, and `(*2) = \x -> x*2`, and `@Int` is type application to specialize `arbitrary` to generate `Int`.

> Have a look at https://hypothesis.works/articles/compositional-shrinking/ and https://hypothesis.works/articles/integrated-shrinking/ for some more write-up, especially about how Hypothesis can preserve information even when shrinking past a monadic bind.

I think what you are hinting at is that, QuickCheck separates generation and shrinking, while Hypothesis combines generation and shrinking. If you prefer combining generation and shrinking, you may want to check out hedgehog in Haskell, see [3] for a discussion of this trade-off.

I think by using the `MonadGen` in hedgehog [4], you should be able to map over and bind over generators, with automatic shrinking, much like Hypothesis.

Hypothesis was first released in 2013, while hedgehog in 2017, so it is possible that hedgehog was inspired by Hypothesis or similar property-based testing libraries.

But in general, I would be surprised if such ‘functional’ APIs (map, filter, reduce, bind, etc.) could not be ported to Haskell.

[1]: https://hackage.haskell.org/package/QuickCheck-2.15.0.1/docs...

[2]: https://hackage.haskell.org/package/QuickCheck-2.15.0.1/docs...

[3]: https://tech.fpcomplete.com/blog/quickcheck-hedgehog-validit...

[4]: https://hackage.haskell.org/package/hedgehog-1.4/docs/Hedgeh...


Yes, I know that `Gen` in QuickCheck is a Monad. What I am saying is `Arbitrary` isn't a Monad.

I know, Arbitrary technically can't be a Monad, because the kinds are wrong. But I mean 'morally': you can fmap the generation process, but you can't fmap the shrinking. Exactly because generation and shrinking are separated; and shrinking is driven purely by the value and type of the generated item, but has no access to any information about the generation process.

> But in general, I would be surprised if such ‘functional’ APIs (map, filter, reduce, bind, etc.) could not be ported to Haskell.

Yes, have a look at the Jack library I already linked to.


Hotwire integrates with Ruby on Rails. (EDIT: The linked page shows how to integrate Hotwire with Ruby on Rails. See fxn's comment https://news.ycombinator.com/item?id=40555577)

I had the same question, then watched the video to get the answer.


No, Hotwire is framework agnostic it is web components and JavaScript, basically.

You can Google Hotwire with Django, or Laravel, or many others (https://hotwire.io/frameworks).


Thanks for the information.

The linked page shows only integrating Hotwire with Ruby on Rails, giving me my original impression.


Some links do not have information yet, others do, for example https://hotwire.io/frameworks/laravel or https://hotwire.io/frameworks/django.


> framework agnostic

Framework agnostic but Ruby-only it seems.


No. Turbo is js and HTML.

If your backend can send templates down the websocket, you can use Hotwire.


Hotwire is in JS and is used by multiple back-end frameworks including Rails.

Rails has a lot of affordances for Hotwire and is the back end framework for which Hotwire was originally written.


No.


Reminds me of nix-output-monitor [1], for example see [2].

It makes it easy to understand how individual steps are progressing, and how individual steps relate to the overall plan. It enables me to locate expensive build steps, and possibly to avoid them if steps are failing.

[1]: https://github.com/maralorn/nix-output-monitor

[2]: https://asciinema.org/a/7hJXH2iFLEkKxG1lL25lspqNn


For those on hyprland:

[1] hyprslidr: https://gitlab.com/magus/hyprslidr

[2] hyprscroller: https://github.com/dawsers/hyprscroller

Though need to extend hyprland to support layout outside viewport: https://github.com/hyprwm/Hyprland/issues/5489


Reminds me of the “Chase your reality” commencement speech by Christopher Nolan at Princeton in 2015.

https://www.youtube.com/watch?v=QoWEhQlS9yY


Software developers often want to customize:

1. their home environments: for packages (some reach for brew on MacOS) and configurations (dotfiles, and some reach for stow).

2. their development shells: for build dependencies (compilers, SDKs, libraries), tools (LSP, linters, formatters, debuggers), and services (runtime, database). Some reach for devcontainers here.

3. or even their operating systems: for development, for CI, for deployment, or for personal use.

Nix provision all of the above in the same language, with Nixpkgs, NixOS, home-manager, and devShells such as https://devenv.sh/. What's more, Nix is (https://nixos.org/):

- reproducible: what works on your dev machine also works in CI and in prod,

- declarative: you version control and review your configurations and infrastructure as code, at a reasonable level of abstraction, to specify what the system should be, not how to get there,

- reliable: all changes (switching generations or profiles) are atomic with easy roll back.


Thank you, it makes sense. I guess these points would resonate with me if I had the problems you describe. Fortunately, I usually don't. The less I fiddle with packages, dot files, shell scripts, the better my life is.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: