haskell / core-libraries-committee

95 stars 16 forks source link

Adding Fix to base #190

Closed alt-romes closed 1 year ago

alt-romes commented 1 year ago

Proposal

This is a proposal to add the Fix datatype to base. Using the constructors from data-fix, Fix is defined as:

newtype Fix f = Fix { unFix :: f (Fix f) }

Fix is a useful, well-known and widely used datatype. However, this datatype seems to be redefined times and times again across different packages. Here's a small list that we ought to increment to motivate the proposal further:

In light of the common need for this datatype, and to avoid duplicating the definition across users, I propose providing Fix in some module in base (Data.Fix would be nice, but that's definitely taken, although...).

Edit: As @phadej mentioned, this also means different packages can provide instances for Fix, like aeson.

Additional considerations

It could be the case that some of these packages do want their own variant of Fix, or for it to instance classes differently, or to have different documentation (though I suppose that could be arranged in the re-exports).

We shouldn't add this to Prelude

Breakage

This is potentially a breaking change, depending on where we define Fix, since all the packages defining Fix can clash with the base definition. However, this is intended breakage. Ideally, these definitions would be dropped in favor of the Fix in base.

Not all Fix definitions are equal (some use out, MkFix, unFix, etc...), so it might not be as trivial as swapping the datatype for some packages.

Alternatives

An alternative to defining just the Fix datatype in some module that cannot clash with Data.Fix in base, we could /merge data-fix/ altogether, and move Data.Fix to base. That has the added benefit of promoting use of recursion schemes, since they're provided in base :)

The Specific Changes

Specifically, I propose to add exactly

newtype Fix f = Fix { unFix :: f (Fix f) }

to a module that avoids clashes (e.g. Data.Recursion.Fix, Data.Fix.Type).

I don't propose anything else. It's not clear which functions we should add together with the definition, under what names (cata vs fold), and it's not bad if functions are duplicated across packages -- as long as the data type they work on is the same. We can consider adding more things besides Fix, but I'd rather keep the proposal as smallest. Additions can be done incrementally by someone with better motivation to do so.

EDIT: We should also consider which instances to give the type, and which documentation. I would appreciate advice on this. Perhaps using the instances from data-fix is a good plan.

Bodigrim commented 1 year ago

@alt-romes if there is no progress on preparing an MR for discusssion, I'll close as abandoned in two weeks.

Bodigrim commented 1 year ago

Closing as abandoned. Feel free to reopen once you get time to prepare an MR.

alt-romes commented 1 year ago

Thanks @Bodigrim, sorry for my non-response.

I am incredibly busy finishing my master thesis. I hope to get back to this after that is done.

Thanks again.