Giter Site home page Giter Site logo

data-fix's People

Contributors

anton-k avatar cstrahan avatar facundominguez avatar flip111 avatar hvr avatar mitchellwrosen avatar phadej avatar ploeh avatar xkollar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

data-fix's Issues

Existentially quantified types for hoistFix

Thank you for the library!

Why existentially quantified types for
hoistFix :: Functor f => (forall a. f a -> g a) -> Fix f -> Fix g
and
hoistFix' :: Functor g => (forall a. f a -> g a) -> Fix f -> Fix g
type annotations. But not simply
hoistFix :: Functor f => (f (Fix g) -> g (Fix g)) -> Fix f -> Fix g
and
hoistFix' :: Functor g => (f (Fix f) -> g (Fix f)) -> Fix f -> Fix g
Probably the original idea behind was to map f -> g to Fix f -> Fix g.
But in fact the proposed method are more general.

Not an issue - just a question about the haskell type system that came to my mind by looking at data-fix

Please excuse if this is a dumb question 😃

Maybe I just missing some special Haskell syntax - but I don't find a good explanation for:

type MyMaybe :: Type -> Type
type MyMaybe = Maybe

type MyMaybe' :: Type -> Type
type MyMaybe' a = Maybe a

type Works = Fix MyMaybe

-- • The type synonym ‘MyMaybe'’ should have 1 argument, but has been given none
-- • In the type synonym declaration for ‘DoesntWork’
type DoesntWork = Fix MyMaybe'

Here for sure the argument can be avoided - but what if the type is nested - e.g. something like Either (Maybe a ) ()? How to apply Fix in such a case?

Add Hashable instance

It would be nice to have a hashable instance for Fix. It could be defined with Hashable1. I would PR this if you would take it.

Use Eq1, Show1, etc. for instances

Since base-4.9, the Data.Functor.Classes module has been available (previously, it was available through the transformers library). It would be nice if the instances for Fix relied on these instead of using FlexibleContexts. I am willing to PR this if you would accept it.

Migrate away from Eq1/Ord1/Show1

Continuing on haskell/core-libraries-committee#190 (comment), I propose to migrate from

instance Eq1 f => Eq (Fix f)
instance Ord1 f => Ord (Fix f)
instance Show1 f => Show (Fix f)

to

instance Eq (f (Fix f)) => Eq (Fix f)
instance Ord (f (Fix f)) => Ord (Fix f)
instance Show (f (Fix f)) => Show (Fix f)

or if you fancy QuantifiedContraints

instance (forall a. Eq a => Eq (f a)) => Eq (Fix f)
instance (forall a. Ord a => Ord (f a)) => Ord (Fix f)
instance (forall a. Show a => Show (f a)) => Show (Fix f)

The motivation is that I recently migrated a codebase from a homegrown newtype Fix with instance Ord (f (Fix f)) => Ord (Fix f) to data-fix and hit performance issues. They were a combination of several factors:

  • I used Data.Functor.Classes.Generic to derive Ord1 instance generically. It appeared that from and to survived in Core, despite pretty aggressive optimization options. This is admittedly not a fault of data-fix, but a general issue with usability of Eq1 / Ord1 / Show1. I had to write all instances manually.

  • class Ord1 contains only liftCompare, but no liftLT, liftLE, liftGT, liftGE, so it has no access to <, <=, >=, > of the base functor. This implies that < on Fix f also necessarily goes through compare and takes a performance hit.

  • It does not seem that liftEq / liftCompare can be optimized away unless the base functor f is completely monomorphic and everything is forced to inline. E. g., (==) specialised to Fix (ListF Int) looks reasonable, but (==) for Fix (ListF a) goes through liftEq. The Core for

    instance Eq (f (Fix f)) => Eq (Fix f) where
      (==) = coerce ((==) @(f (Fix f)))

    looks more reasonable to me.


I understand that the proposed change is a breaking one. It is however not very pronounced: in recent base we have class (forall a. Eq f a) => Eq1 f, so the majority of users will not even notice. It's only if you require Eq (Fix f) as a constraint, but use liftEq inside, which will explode, because Eq1 f is no longer guaranteed. I think, however, that GHC would yell if encounters Eq (Fix f) constraint, suggesting to replace it with Eq1 f.

@phadej what do you think?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.