1{-# LANGUAGE FlexibleContexts #-}
2{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE MultiParamTypeClasses #-}
4{-# LANGUAGE ScopedTypeVariables #-}
5{-# LANGUAGE TypeOperators #-}
6{-# LANGUAGE TypeSynonymInstances #-}
7{-# LANGUAGE UndecidableInstances #-}
9-----------------------------------------------------------------------------
11-- Module : Data.Generics.Sum.Subtype
12-- Copyright : (C) 2017 Csongor Kiss
14-- Maintainer : Csongor Kiss <kiss.csongor.kiss@gmail.com>
15-- Stability : experimental
16-- Portability : non-portable
18-- Structural subtype relationships between sum types.
20-----------------------------------------------------------------------------
22module Data.Generics.Sum.Subtype
29import Data.Generics.Internal.Lens
30import Data.Generics.Sum.Internal.Subtype
32import GHC.Generics (Generic (Rep, to, from))
36-- module Example where
38-- import Data.Generics.Sum
45-- deriving (Generic, Show)
47-- data FourLeggedAnimal
50-- deriving (Generic, Show)
56-- deriving (Generic, Show)
61-- dog, cat, duck :: Animal
63-- dog = Dog (MkDog "Shep" 3)
67-- dog4, cat4 :: FourLeggedAnimal
69-- dog4 = Dog4 (MkDog "Snowy" 4)
70-- cat4 = Cat4 "Garfield" 6
73-- |Structural subtyping between sums. A sum 'Sub' is a subtype of another sum
74-- 'Sup' if a value of 'Sub' can be given (modulo naming of constructors)
75-- whenever a value of 'Sup' is expected. In the running example for instance,
76-- 'FourLeggedAnimal` is a subtype of 'Animal' since a value of the former can
77-- be given as a value of the latter (renaming 'Dog4' to 'Dog' and 'Cat4' to
79class AsSubtype sub sup where
80 -- |A prism that captures structural subtyping. Allows a substructure to be
81 -- injected (upcast) into a superstructure or a superstructure to be downcast
82 -- into a substructure (which may fail).
84 -- >>> _Sub # dog4 :: Animal
85 -- Dog (MkDog {name = "Snowy", age = 4})
86 -- >>> cat ^? _Sub :: Maybe FourLeggedAnimal
87 -- Just (Cat4 "Mog" 5)
88 -- >>> duck ^? _Sub :: Maybe FourLeggedAnimal
90 _Sub :: Prism' sup sub
91 _Sub = prism injectSub projectSub
93 -- |Injects a subtype into a supertype (upcast).
94 injectSub :: sub -> sup
96 -- |Projects a subtype from a supertype (downcast).
97 projectSub :: sup -> Either sup sub
99 {-# MINIMAL injectSub, projectSub #-}
104 , GAsSubtype (Rep sub) (Rep sup)
105 ) => AsSubtype sub sup where
107 injectSub = to . ginjectSub . from
108 projectSub = either (Left . to) (Right . to) . gprojectSub . from
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list