1
1
mirror of https://github.com/srid/ema.git synced 2024-12-01 15:13:36 +03:00

Replace Coercible with GIsomorphic

This commit is contained in:
Sridhar Ratnakumar 2022-07-01 12:46:21 -04:00
parent 672467dea8
commit 760fd79310
5 changed files with 30 additions and 12 deletions

View File

@ -33,6 +33,7 @@ data Model = Model
newtype Slug = Slug Text
deriving newtype (Show, Eq, Ord, IsString, ToString, FromJSON, FromJSONKey)
deriving stock (Generic)
newtype Product = Product {unProduct :: Text}
deriving newtype (Show, Eq, Ord, IsString, ToString, FromJSON)

View File

@ -37,7 +37,7 @@ instance HasSubRoutes R where
-}
data NumRoute = NumRoute
deriving stock (Show, Eq)
deriving stock (Show, Eq, Generic)
instance IsRoute NumRoute where
type RouteModel NumRoute = Int

View File

@ -25,9 +25,10 @@ import GHC.TypeLits.Extra.Symbol (StripPrefix, ToLower)
#else
import GHC.TypeLits
#endif
import Generics.SOP (All, I (..), NS, SameShapeAs, Top)
import GHC.Generics qualified as GHC
import Generics.SOP (All, I (..), NS, SameShapeAs, Top, unI)
import Generics.SOP.Type.Metadata qualified as SOPM
import Optics.Core (Iso', iso)
import Optics.Core (Iso', iso, view)
import Prelude hiding (All)
{- | HasSubRoutes is a class of routes with an underlying MultiRoute (and MultiModel) representation.
@ -77,7 +78,7 @@ gtoSubRoutes ::
) =>
NS I (RCode r) ->
MultiRoute subRoutes
gtoSubRoutes = trans_NS (Proxy @Coercible) coerce
gtoSubRoutes = trans_NS (Proxy @GIsomorphic) (I . view giso . unI)
gfromSubRoutes ::
forall r subRoutes.
@ -86,7 +87,7 @@ gfromSubRoutes ::
) =>
MultiRoute subRoutes ->
NS I (RCode r)
gfromSubRoutes = trans_NS (Proxy @Coercible) coerce
gfromSubRoutes = trans_NS (Proxy @GIsomorphic) (I . view giso . unI)
-- | @subRoutes@ are valid sub-routes of @r@
type ValidSubRoutes r subRoutes =
@ -94,10 +95,26 @@ type ValidSubRoutes r subRoutes =
, SameShapeAs subRoutes (RCode r)
, All Top (RCode r)
, All Top subRoutes
, AllZipF Coercible (RCode r) subRoutes
, AllZipF Coercible subRoutes (RCode r)
, AllZipF GIsomorphic (RCode r) subRoutes
, AllZipF GIsomorphic subRoutes (RCode r)
)
{- | Types `a` and `b` are isomorphic via their generic representation
Unlike `Coercible` this constraint does not require that the two types have
identical *runtime* representation. For example, `data Foo = Foo` is not
coercible to `()` (they have different runtime representations), but they are
both isomorphic via their generic representation.
-}
class (Generic a, Generic b, GHC.Rep a () `Coercible` GHC.Rep b ()) => GIsomorphic a b where
giso :: Iso' a b
instance (Generic a, Generic b, GHC.Rep a () `Coercible` GHC.Rep b ()) => GIsomorphic a b where
giso =
iso
(GHC.to @b @() . coerce . GHC.from @a @())
(GHC.to @a @() . coerce . GHC.from @b @())
#if MIN_VERSION_GLASGOW_HASKELL(9,2,0,0)
type family GSubRoutes (name :: SOPM.DatatypeName) (constrs :: [SOPM.ConstructorName]) (xs :: [Type]) :: [Type] where
GSubRoutes _ _ '[] = '[]

View File

@ -16,13 +16,13 @@ import Optics.Core (equality, prism')
TODO: Can this type be simplified? See https://stackoverflow.com/q/72755053/55246
-}
newtype FileRoute (filename :: Symbol) = FileRoute ()
deriving stock (Eq, Ord, Show)
data FileRoute (filename :: Symbol) = FileRoute
deriving stock (Eq, Ord, Show, Generic)
instance KnownSymbol fn => IsRoute (FileRoute fn) where
type RouteModel (FileRoute fn) = ()
routeEncoder =
singletonRouteEncoder (symbolVal (Proxy @fn))
& mapRouteEncoder equality (prism' (const ()) (const $ Just $ FileRoute ())) id
& mapRouteEncoder equality (prism' (const ()) (const $ Just FileRoute)) id
allRoutes () =
[FileRoute ()]
[FileRoute]

View File

@ -17,7 +17,7 @@ import Text.Show (Show (show))
-- | A route that is prefixed at some URL prefix
newtype FolderRoute (prefix :: Symbol) r = FolderRoute {unFolderRoute :: r}
deriving newtype (Eq, Ord)
deriving newtype (Eq, Ord, Generic)
instance (Show r, KnownSymbol prefix) => Show (FolderRoute prefix r) where
show (FolderRoute r) = symbolVal (Proxy @prefix) <> "/:" <> Text.Show.show r