Skip to content

Instantly share code, notes, and snippets.

@zyla
Created February 28, 2018 17:49
Show Gist options
  • Save zyla/3dcdc23d24c259fb166844759be8d05d to your computer and use it in GitHub Desktop.
Save zyla/3dcdc23d24c259fb166844759be8d05d to your computer and use it in GitHub Desktop.
-- | 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