Last active
January 30, 2020 13:05
-
-
Save soupi/c9048ca0d53c8a3c67f7f9a217748003 to your computer and use it in GitHub Desktop.
implementation of transform using generics
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
data Expr | |
= Lit Int | |
| Add Expr Expr | |
| Mul Expr Expr | |
| Div Expr Expr | |
| Sub Expr Expr | |
| Neg Expr | |
deriving (Show, Eq, Generic) | |
-- Transform -- | |
class GTransform a struct where | |
gtransform :: (a -> a) -> struct x -> struct x | |
instance GTransform a U1 where | |
gtransform _ U1 = U1 | |
instance GTransform a V1 where | |
gtransform _ x = x | |
instance {-# OVERLAPPING #-} Transform a => GTransform a (K1 _1 a) where | |
gtransform f (K1 a) = K1 (f $ transform f a) | |
instance Transform b => GTransform a (K1 _1 b) where | |
gtransform f (K1 b) = K1 (transform f b) | |
instance (GTransform a x, GTransform a y) => GTransform a (x :+: y) where | |
gtransform f = \case | |
L1 x -> L1 $ gtransform f x | |
R1 y -> R1 $ gtransform f y | |
instance (GTransform a x, GTransform a y) => GTransform a (x :*: y) where | |
gtransform f (x :*: y) = gtransform f x :*: gtransform f y | |
instance GTransform a struct => GTransform a (M1 _x _y struct) where | |
gtransform f (M1 a) = M1 $ gtransform f a | |
class Transform x where | |
transform :: (a -> a) -> x -> x | |
default transform :: forall a. (Generic x, GTransform a (Rep x)) => (a -> a) -> x -> x | |
transform f = to . gtransform f . from | |
instance Transform Int where | |
transform = flip const | |
instance Transform Expr | |
{- ^ | |
generics.hs:101:10: error: | |
• Overlapping instances for GTransform a (K1 R Int) | |
arising from a use of ‘Main.$dmtransform’ | |
Matching instances: | |
two instances involving out-of-scope types | |
(use -fprint-potential-instances to see them all) | |
(The choice depends on the instantiation of ‘a’ | |
To pick the first instance above, use IncoherentInstances | |
when compiling the other instance declarations) | |
• In the expression: Main.$dmtransform @(Expr) | |
In an equation for ‘transform’: | |
transform = Main.$dmtransform @(Expr) | |
In the instance declaration for ‘Transform Expr’ | |
| | |
101 | instance Transform Expr | |
| ^^^^^^^^^^^^^^ | |
-} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment