@@ -0,0 +1,58 @@
1+{-# language ConstraintKinds #-}
2+{-# language DataKinds #-}
3+{-# language FlexibleContexts #-}
4+{-# language FlexibleInstances #-}
5+{-# language FunctionalDependencies #-}
6+{-# language MultiParamTypeClasses #-}
7+{-# language ScopedTypeVariables #-}
8+{-# language TypeFamilies #-}
9+{-# language TypeOperators #-}
10+{-# language UndecidableInstances #-}
11+module Data.Generics.Iso
12+ ( Is(..)
13+ , _Unwrapped
14+ , _Wrapped
15+ )
16+where
17+
18+import Data.Generics.Internal.VL.Iso as VL
19+import Data.Generics.Internal.VL.Lens ((^.))
20+
21+import Data.Kind (Constraint)
22+import GHC.Generics
23+import GHC.TypeLits
24+
25+class GIso a b | a -> b where
26+ gIso :: Iso' (a x) b
27+
28+instance GIso a b => GIso (M1 i k a) b where
29+ gIso = mIso.gIso
30+
31+instance GIso (K1 i c) c where
32+ gIso = kIso
33+
34+class Is a b | a -> b where
35+ {-# minimal _Is | isTo, isFrom #-}
36+ _Is :: VL.Iso' a b
37+ _Is = iso isTo isFrom
38+
39+ isTo :: a -> b
40+ isTo a = a ^. _Is
41+
42+ isFrom :: b -> a
43+ isFrom a = a ^. fromIso _Is
44+
45+type family ErrorUnlessOnlyOne a b :: Constraint where
46+ ErrorUnlessOnlyOne t (M1 i k a) = ErrorUnlessOnlyOne t a
47+ ErrorUnlessOnlyOne t (K1 i a) = ()
48+ ErrorUnlessOnlyOne t a =
49+ TypeError ('ShowType t ':<>: 'Text " is not a single-constructor, single-field datatype")
50+
51+instance (Generic a, ErrorUnlessOnlyOne a (Rep a), GIso (Rep a) b) => Is a b where
52+ _Is = repIso . gIso
53+
54+_Unwrapped :: Is a b => Iso' a b
55+_Unwrapped = _Is
56+
57+_Wrapped :: Is a b => Iso' b a
58+_Wrapped = fromIso _Is