@@ -11,9 +11,26 @@
1111{-# LANGUAGE TypeOperators #-}
1212{-# LANGUAGE UndecidableInstances #-}
1313
14+-----------------------------------------------------------------------------
15+-- |
16+-- Module : Data.Generics.Product.Any
17+-- Copyright : (C) 2017 Csongor Kiss
18+-- License : BSD3
19+-- Maintainer : Csongor Kiss <kiss.csongor.kiss@gmail.com>
20+-- Stability : experimental
21+-- Portability : non-portable
22+--
23+-- Derive constructor-field-type-based prisms generically.
24+--
25+-----------------------------------------------------------------------------
26+
1427module Data.Generics.Sum.Typed
15− ( AsType (..)
28+ ( -- *Prisms
29+ --
30+ -- $example
31+ AsType (..)
1632
33+ -- *Internals
1734 , GAsType (..)
1835 ) where
1936
@@ -25,19 +42,58 @@ import Data.Kind
2542import GHC.Generics
2643import GHC.TypeLits
2744
45+-- $example
46+-- @
47+-- module Example where
48+--
49+-- import Data.Generics.Sum
50+-- import GHC.Generics
51+--
52+-- data Animal
53+-- = Dog Dog
54+-- | Cat (Name, Age)
55+-- | Duck Age
56+-- deriving (Generic, Show)
57+--
58+-- data Dog = MkDog
59+-- { name :: Name
60+-- , age :: Age
61+-- }
62+-- deriving (Generic, Show)
63+--
64+-- type Name = String
65+-- type Age = Int
66+--
67+-- dog, cat, duck :: Animal
68+--
69+-- dog = Dog (MkDog "Shep" 3)
70+-- cat = Cat ("Mog", 5)
71+-- duck = Duck 2
72+-- @
73+
74+-- |Sums that have a constructor with a field of the given type.
2875class AsType a s where
76+ -- |A prism that projects a constructor uniquely identifiable by the type of
77+ -- its field. Compatible with the lens package's 'Control.Lens.Prism' type.
78+ --
79+ -- >>> dog ^? _Typed @Dog
80+ -- Just (MkDog {name = "Shep", age = 3})
81+ -- >>> dog ^? _Typed @Cat
82+ -- Nothing
83+ -- >>> duck ^? _Typed @Age
84+ -- Just 2
2985 _Typed :: Prism' s a
3086
3187instance
3288 ( Generic s
33− , ErrorUnless a s (HasPartialTypeP a (Rep s))
89+ , ErrorUnlessOne a s (CountPartialType a (Rep s))
3490 , GAsType (Rep s) a
3591 ) => AsType a s where
3692
3793 _Typed = repIso . _GTyped
3894
39−type family ErrorUnless (a :: Type) (s :: Type) (contains :: Bool) :: Constraint where
40− ErrorUnless a s 'False
95+type family ErrorUnlessOne (a :: Type) (s :: Type) (count :: Count) :: Constraint where
96+ ErrorUnlessOne a s 'None
4197 = TypeError
4298 ( 'Text "The type "
4399 ':<>: 'ShowType s
@@ -45,9 +101,19 @@ type family ErrorUnless (a :: Type) (s :: Type) (contains :: Bool) :: Constraint
45101 ':<>: 'ShowType a
46102 )
47103
48− ErrorUnless _ _ 'True
104+ ErrorUnlessOne a s 'Multiple
105+ = TypeError
106+ ( 'Text "The type "
107+ ':<>: 'ShowType s
108+ ':<>: 'Text " contains multiple constructors whose fields are of type "
109+ ':<>: 'ShowType a
110+ ':<>: 'Text "; the choice of constructor is thus ambiguous"
111+ )
112+
113+ ErrorUnlessOne _ _ 'One
49114 = ()
50115
116+-- |As 'AsType' but over generic representations as defined by "GHC.Generics".
51117class GAsType (f :: Type -> Type) a where
52118 _GTyped :: Prism' (f x) a
53119