Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Index TypeFamily for Ixed/At inconsistent with FunDeps for *WithIndex #1004

Open
tysonzero opened this issue Apr 24, 2022 · 3 comments
Open

Comments

@tysonzero
Copy link

Is there a particular reason for this inconsistency?

It seems like just using a single type family Index for both would be ideal. I realize such a type family would have to be floated up to indexed-traversable

@phadej
Copy link
Collaborator

phadej commented Apr 25, 2022

there is a kind issue:

class Functor f => FunctorWithIndex i f | f -> i where -- f :: Type -> Type

-- but

type family Index (s :: Type) :: Type  -- s :: Type

so these cannot be easily the same.

Why one is TF and onther is FD, I don't know exactly. Index is used by bothIx and Contains classes, but that can be done with (anonymous) FD as well. (I like FDs more, but I guess i'm in minority in that: EDIT: IMHO non-associated open type family is the worst option).

@tysonzero
Copy link
Author

tysonzero commented Apr 25, 2022

It's a little awkward with the kind mismatch as you have to use a somewhat dummy a in Index (f a), but I can't seem to find any major downsides?

class FunctorWithIndex f where
    imap :: (Index (f a) -> a -> b) -> f a -> f b

type instance Index [a] = Int 

instance FunctorWithIndex [] where
    imap f = zipWith f [0 ..]

I'm biased towards TypeFamilies, partly because they just feel more composable and functional, but also largely just because I think instance heads should be very simple and clearly decidable.

Various things I want to do that really aren't all that complicated require UndecidableInstances (and the currently incoherent FlexibleInstances) when done with FD's that don't require anything beyond TypeFamilies when done with TFs. Even outside the extensions, when glancing at them I can't quickly tell as a developer that the instances are reasonable without looking through the FD's at the class definition and mentally ignoring all the variables to the right of an arrow.

I also like being able to immediately tell that Index s is a function of s in a type signature, instead of having to look up the class definition or guess if s and i are related or what have you.

@phadej
Copy link
Collaborator

phadej commented Apr 26, 2022

but I can't seem to find any major downsides?

Index (f a) can depend on element type a. E.g. if you try to state imap f . imap g ≡ imap (\i -> f i . g i) law, you'd need forall a b. Index a ~ Index b like requirement.

This is matter of taste. I prefer FDs for this use case (and e.g. Each, where TFs would create a complete mess).

This is also be a major breaking change, affecting a lot of people for a what I would say a stylistic benefit. Not worth considering.

EDIT: indexed-traversable is also used by optics, and I used it in projects not using lens or optics (e.g. witherable).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants