Created
February 28, 2018 17:49
-
-
Save zyla/3dcdc23d24c259fb166844759be8d05d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- | Failed experiment in generically deriving a `Functor` instance. | |
-- | Requires PureScript HEAD (what will be 0.12), and still doesn't compile :/ | |
module Data.Generic.Rep.Functor | |
( class GenericMap | |
, genericMap' | |
) where | |
import Prelude | |
import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), Field(..), NoArguments(..), Product(..), Rec(..), Sum(..), from, to) | |
class GenericMap a b fa fb where | |
genericMap' :: (a -> b) -> fa -> fb | |
instance genericMapNoArguments :: GenericMap a b NoArguments NoArguments where | |
genericMap' f NoArguments = NoArguments | |
instance genericMapProduct :: (GenericMap a b fa fb, GenericMap a b ga gb) => GenericMap a b (Product fa ga) (Product fb gb) where | |
genericMap' f (Product x y) = Product (genericMap' f x) (genericMap' f y) | |
instance genericMapSum :: | |
( GenericMap a b fa fb | |
, GenericMap a b ga gb | |
) | |
=> GenericMap a b (Sum fa ga) (Sum fb gb) where | |
genericMap' f (Inl x) = Inl (genericMap' f x) | |
genericMap' f (Inr y) = Inr (genericMap' f y) | |
instance genericMapConstructor :: GenericMap a b fa fb => GenericMap a b (Constructor name fa) (Constructor name fb) where | |
genericMap' f (Constructor x) = Constructor (genericMap' f x) | |
instance genericMapArgumentI :: GenericMap a b (Argument a) (Argument b) where | |
genericMap' f (Argument x) = Argument (f x) | |
else instance genericMapArgumentK :: GenericMap a b (Argument x) (Argument x) where | |
genericMap' f (Argument x) = Argument x | |
instance genericMapRec :: GenericMap a b fa fb => GenericMap a b (Rec fa) (Rec fb) where | |
genericMap' f (Rec x) = Rec (genericMap' f x) | |
instance genericMapFieldI :: GenericMap a b (Field name a) (Field name b) where | |
genericMap' f (Field x) = Field (f x) | |
else instance genericMapFieldK :: GenericMap a b (Field name x) (Field name x) where | |
genericMap' f (Field x) = Field x | |
genericMap :: forall f a b fa fb. Generic (f a) fa => Generic (f b) fb => GenericMap a b fa fb => (a -> b) -> f a -> f b | |
genericMap f = to <<< genericMap' f <<< from | |
data D a = C1 | C2 a Int | |
derive instance genericD :: Generic (D a) _ | |
instance functorD :: Functor D where map = genericMap | |
{- | |
No type class instance was found for | |
|| | |
|| Data.Generic.Rep.Functor.GenericMap a0 | |
|| b1 | |
|| (Argument Int) | |
|| (Argument Int) | |
The type checker can't commit to `genericMapArgumentK`, because that would | |
require `a` and `b` being _apart_ from Int. That's obviously not the case, | |
since we could substitute Int for `a`. | |
Swapping the order of instances for Argument doesn't help - then the type | |
checked fails to commit to `genericMapArgumentI`, since it would require `a` | |
being apart from `b`. | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment