@@ -1,4 +1,3 @@
2{-# LANGUAGE ApplicativeDo #-}
1{-# LANGUAGE ApplicativeDo #-}
3{-# LANGUAGE ConstraintKinds #-}
2{-# LANGUAGE ConstraintKinds #-}
4{-# LANGUAGE EmptyCase #-}
3{-# LANGUAGE EmptyCase #-}
@@ -6,6 +5,7 @@
6{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleContexts #-}
7{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FlexibleInstances #-}
8{-# LANGUAGE GADTs #-}
7{-# LANGUAGE GADTs #-}
8+{-# LANGUAGE KindSignatures #-}
9{-# LANGUAGE LambdaCase #-}
9{-# LANGUAGE LambdaCase #-}
10{-# LANGUAGE MultiParamTypeClasses #-}
10{-# LANGUAGE MultiParamTypeClasses #-}
11{-# LANGUAGE OverloadedStrings #-}
11{-# LANGUAGE OverloadedStrings #-}
@@ -61,7 +61,6 @@ module Obelisk.Route
61 , justEncoder
61 , justEncoder
62 , nothingEncoder
62 , nothingEncoder
63 , isoEncoder
63 , isoEncoder
65 , wrappedEncoder
64 , wrappedEncoder
66 , unwrappedEncoder
65 , unwrappedEncoder
67 , listToNonEmptyEncoder
66 , listToNonEmptyEncoder
@@ -70,7 +69,6 @@ module Obelisk.Route
70 , toListMapEncoder
69 , toListMapEncoder
71 , shadowEncoder
70 , shadowEncoder
72 , prismEncoder
71 , prismEncoder
76 , obeliskRouteEncoder
74 , obeliskRouteEncoder
@@ -135,24 +133,20 @@ import Control.Lens
140 , Wrapped (..)
137 , Wrapped (..)
142import Control.Monad.Except
139import Control.Monad.Except
140+import Control.Monad.Writer (execWriter, tell)
143import qualified Control.Monad.State.Strict as State
141import qualified Control.Monad.State.Strict as State
144import Control.Monad.Trans (lift)
142import Control.Monad.Trans (lift)
145−import Control.Monad.Writer (execWriter, tell)
146−import Data.Aeson (FromJSON, ToJSON)
147−import qualified Data.Aeson as Aeson
148import qualified Data.ByteString as BS
143import qualified Data.ByteString as BS
149import qualified Data.ByteString.Lazy as BSL
144import qualified Data.ByteString.Lazy as BSL
145+import Data.Dependent.Sum (DSum (..))
150import Data.Dependent.Map (DMap)
146import Data.Dependent.Map (DMap)
151import qualified Data.Dependent.Map as DMap
147import qualified Data.Dependent.Map as DMap
152−import Data.Dependent.Sum (DSum (..))
153import Data.Either.Validation (Validation (..))
148import Data.Either.Validation (Validation (..))
154import Data.Foldable
149import Data.Foldable
155−import Data.Functor (($>))
156import Data.Functor.Sum
150import Data.Functor.Sum
157import Data.GADT.Compare
151import Data.GADT.Compare
158import Data.GADT.Compare.TH
152import Data.GADT.Compare.TH
@@ -165,18 +159,19 @@ import Data.Monoid ((<>))
165import Data.Set (Set)
159import Data.Set (Set)
166import qualified Data.Set as Set
160import qualified Data.Set as Set
167import Data.Some (Some(Some))
161import Data.Some (Some(Some))
168−import Data.Tabulation
169import Data.Text (Text)
162import Data.Text (Text)
163+import Data.Text.Lens (IsText, packed, unpacked)
170import qualified Data.Text as T
164import qualified Data.Text as T
171import qualified Data.Text.Encoding as T
165import qualified Data.Text.Encoding as T
172−import Data.Text.Lens (IsText, packed, unpacked)
173−import Data.Type.Equality
174import Data.Universe
166import Data.Universe
175import Data.Universe.Some
167import Data.Universe.Some
176import Network.HTTP.Types.URI
168import Network.HTTP.Types.URI
177import qualified Numeric.Lens
169import qualified Numeric.Lens
178import Obelisk.Route.TH
170import Obelisk.Route.TH
179import Text.Read (readMaybe)
171import Text.Read (readMaybe)
172+import Data.Tabulation
173+import qualified Data.Aeson as Aeson
174+import Data.Aeson (FromJSON, ToJSON)
181-- Design goals:
176-- Design goals:
182-- No start-up time on the frontend (not yet met)
177-- No start-up time on the frontend (not yet met)
@@ -226,19 +221,7 @@ hoistR f (x :=> Identity y) = f x :/ y
226infixr 5 :.
221infixr 5 :.
227type (:.) = (,)
222type (:.) = (,)
229−#ifdef __GLASGOW_HASKELL__
230−#if __GLASGOW_HASKELL__ >= 810
231{-# COMPLETE (:.) #-}
224{-# COMPLETE (:.) #-}
234− [ "Use of this pattern in GHC < 8.10 will result in spurious non-exhaustive warnings at every use site."
235− , "We cannot provide a COMPLETE pragma to silence these due to a GHC bug: https://gitlab.haskell.org/ghc/ghc/issues/17729."
236− , "The bug hides incompleteness warnings for all two tuples when the COMPLETE pattern is in scope."
237− , "Instead, you should use (,) directly until you can switch to GHC >= 8.10, where the COMPLETE pragma is reinstated."
242pattern (:.) :: a -> b -> a :. b
225pattern (:.) :: a -> b -> a :. b
243pattern a :. b = (a, b)
226pattern a :. b = (a, b)
@@ -304,13 +287,13 @@ decode e x = runIdentity (tryDecode e x)
304-- | Once an 'Encoder' has been checked, so that its check monad has become 'Identity', even if the same is not true of the
287-- | Once an 'Encoder' has been checked, so that its check monad has become 'Identity', even if the same is not true of the
305-- parse monad, we may still attempt to decode with it in its parse monad.
288-- parse monad, we may still attempt to decode with it in its parse monad.
306tryDecode :: Encoder Identity parse decoded encoded -> encoded -> parse decoded
289tryDecode :: Encoder Identity parse decoded encoded -> encoded -> parse decoded
307−tryDecode (Encoder (Identity impl)) = _encoderImpl_decode impl
290+tryDecode (Encoder (Identity impl)) x = _encoderImpl_decode impl x
309-- | Similar to 'decode', once an encoder has been checked so that its check monad is Identity, it
292-- | Similar to 'decode', once an encoder has been checked so that its check monad is Identity, it
310-- can be used to actually encode by using this. Note that while there's no constraint on the parse monad here,
293-- can be used to actually encode by using this. Note that while there's no constraint on the parse monad here,
311-- one should usually be applying decode and encode to the same 'Encoder'
294-- one should usually be applying decode and encode to the same 'Encoder'
312encode :: Encoder Identity parse decoded encoded -> decoded -> encoded
295encode :: Encoder Identity parse decoded encoded -> decoded -> encoded
313−encode (Encoder (Identity impl)) = _encoderImpl_encode impl
296+encode (Encoder (Identity impl)) x = _encoderImpl_encode impl x
315-- | This is a primitive used to build encoders which can't fail to check. It should not be used unless one is
298-- | This is a primitive used to build encoders which can't fail to check. It should not be used unless one is
316-- reasonably certain that the law given for 'EncoderImpl' above holds.
299-- reasonably certain that the law given for 'EncoderImpl' above holds.
@@ -357,7 +340,7 @@ instance Monad parse => Bifunctor (,) (EncoderImpl parse) (EncoderImpl parse) (E
359instance (Monad parse, Applicative check) => Braided (Encoder check parse) (,) where
342instance (Monad parse, Applicative check) => Braided (Encoder check parse) (,) where
360− braid = viewEncoder (iso swap swap)
343+ braid = isoEncoder (iso swap swap)
363instance (Applicative check, Monad parse) => PFunctor (,) (Encoder check parse) (Encoder check parse) where
346instance (Applicative check, Monad parse) => PFunctor (,) (Encoder check parse) (Encoder check parse) where
@@ -393,11 +376,11 @@ instance (Monad parse, Applicative check) => Bifunctor Either (Encoder check par
393 bimap f g = Encoder $ liftA2 bimap (unEncoder f) (unEncoder g)
376 bimap f g = Encoder $ liftA2 bimap (unEncoder f) (unEncoder g)
395instance (Applicative check, Monad parse) => Associative (Encoder check parse) Either where
378instance (Applicative check, Monad parse) => Associative (Encoder check parse) Either where
396− associate = viewEncoder (iso (associate @(->) @Either) disassociate)
379+ associate = isoEncoder (iso (associate @(->) @Either) disassociate)
397− disassociate = viewEncoder (iso disassociate associate)
380+ disassociate = isoEncoder (iso disassociate associate)
399instance (Monad parse, Applicative check) => Braided (Encoder check parse) Either where
382instance (Monad parse, Applicative check) => Braided (Encoder check parse) Either where
400− braid = viewEncoder (iso swap swap)
383+ braid = isoEncoder (iso swap swap)
@@ -451,17 +434,17 @@ instance (Applicative check, Monad parse) => Monoidal (Encoder check parse) (,)
451--------------------------------------------------------------------------------
434--------------------------------------------------------------------------------
453-- | Given a valid 'Iso' from lens, construct an 'Encoder'
436-- | Given a valid 'Iso' from lens, construct an 'Encoder'
454−viewEncoder :: (Applicative check, Applicative parse) => Iso' a b -> Encoder check parse a b
437+isoEncoder :: (Applicative check, Applicative parse) => Iso' a b -> Encoder check parse a b
455−viewEncoder f = unsafeMkEncoder $ EncoderImpl
438+isoEncoder f = unsafeMkEncoder $ EncoderImpl
456 { _encoderImpl_encode = view f
439 { _encoderImpl_encode = view f
457 , _encoderImpl_decode = pure . view (from f)
440 , _encoderImpl_decode = pure . view (from f)
460wrappedEncoder :: (Wrapped a, Applicative check, Applicative parse) => Encoder check parse (Unwrapped a) a
443wrappedEncoder :: (Wrapped a, Applicative check, Applicative parse) => Encoder check parse (Unwrapped a) a
461−wrappedEncoder = viewEncoder $ from _Wrapped'
444+wrappedEncoder = isoEncoder $ from _Wrapped'
463unwrappedEncoder :: (Wrapped a, Applicative check, Applicative parse) => Encoder check parse a (Unwrapped a)
446unwrappedEncoder :: (Wrapped a, Applicative check, Applicative parse) => Encoder check parse a (Unwrapped a)
464−unwrappedEncoder = viewEncoder $ _Wrapped'
447+unwrappedEncoder = isoEncoder _Wrapped'
466maybeToEitherEncoder :: (Applicative check, Applicative parse) => Encoder check parse (Maybe a) (Either () a)
449maybeToEitherEncoder :: (Applicative check, Applicative parse) => Encoder check parse (Maybe a) (Either () a)
467maybeToEitherEncoder = unsafeMkEncoder $ EncoderImpl
450maybeToEitherEncoder = unsafeMkEncoder $ EncoderImpl
@@ -486,11 +469,11 @@ maybeEncoder f g = shadowEncoder f g . maybeToEitherEncoder
487-- | Encode a value by simply applying 'Just'
470-- | Encode a value by simply applying 'Just'
488justEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse a (Maybe a)
471justEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse a (Maybe a)
489−justEncoder = reviewEncoder _Just
472+justEncoder = prismEncoder _Just
491-- | Encode () to 'Nothing'.
474-- | Encode () to 'Nothing'.
492nothingEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse () (Maybe a)
475nothingEncoder :: (Applicative check, MonadError Text parse) => Encoder check parse () (Maybe a)
493−nothingEncoder = reviewEncoder _Nothing
476+nothingEncoder = prismEncoder _Nothing
495someConstEncoder :: (Applicative check, Applicative parse) => Encoder check parse (Some (Const a)) a
478someConstEncoder :: (Applicative check, Applicative parse) => Encoder check parse (Some (Const a)) a
496someConstEncoder = unsafeMkEncoder $ EncoderImpl
479someConstEncoder = unsafeMkEncoder $ EncoderImpl
@@ -555,11 +538,11 @@ pathComponentEncoder f = Encoder $ do
555 unEncoder (pathComponentEncoderImpl (enum1Encoder (extractPathSegment . f)) f')
538 unEncoder (pathComponentEncoderImpl (enum1Encoder (extractPathSegment . f)) f')
557pathComponentEncoderImpl :: forall check parse p. (Monad check, Monad parse)
540pathComponentEncoderImpl :: forall check parse p. (Monad check, Monad parse)
558− => Encoder check parse (Some p) (Maybe Text)
541+ => (Encoder check parse (Some p) (Maybe Text))
559 -> (forall a. p a -> Encoder Identity parse a PageName)
542 -> (forall a. p a -> Encoder Identity parse a PageName)
560 -> Encoder check parse (R p) PageName
543 -> Encoder check parse (R p) PageName
561−pathComponentEncoderImpl =
544+pathComponentEncoderImpl this rest =
562− chainEncoder (lensEncoder (\(_, b) a -> (a, b)) Prelude.fst consEncoder)
545+ chainEncoder (lensEncoder (\(_, b) a -> (a, b)) Prelude.fst consEncoder) this rest
564--NOTE: Naming convention in this module is to always talk about things in the *encoding* direction, never in the *decoding* direction
547--NOTE: Naming convention in this module is to always talk about things in the *encoding* direction, never in the *decoding* direction
@@ -815,7 +798,7 @@ rPrism
815 :: forall f f'
798 :: forall f f'
816 . (forall a. Prism' (f a) (f' a))
799 . (forall a. Prism' (f a) (f' a))
817 -> Prism' (R f) (R f')
800 -> Prism' (R f) (R f')
818−rPrism = dSumPrism
801+rPrism p = dSumPrism p
820dSumPrism'
803dSumPrism'
821 :: forall f g a
804 :: forall f g a
@@ -827,7 +810,7 @@ dSumGEqPrism
829 -> Prism' (DSum f g) (g a)
812 -> Prism' (DSum f g) (g a)
830−dSumGEqPrism variant = dSumPrism' $ prism' (\Refl -> variant) (geq variant)
813+dSumGEqPrism variant = dSumPrism' $ prism' (\Refl -> variant) (\x -> geq variant x)
832-- | Given a 'tag :: f a', make a prism for 'R f'. This generalizes the usual
815-- | Given a 'tag :: f a', make a prism for 'R f'. This generalizes the usual
833-- prisms for a sum type (the ones that 'mkPrisms' would make), just as 'R'
816-- prisms for a sum type (the ones that 'mkPrisms' would make), just as 'R'
@@ -844,19 +827,12 @@ _R variant = dSumGEqPrism variant . iso runIdentity Identity
845-- | An encoder that only works on the items available via the prism. An error will be thrown in the parse monad
828-- | An encoder that only works on the items available via the prism. An error will be thrown in the parse monad
846-- if the prism doesn't match.
829-- if the prism doesn't match.
848−-- Note that a 'Prism' from @a@ to @b@ will produce an 'Encoder' from @b@ to @a@
849−-- (i.e. 'reviewEncoder' is a contravariant functor from the category of prisms to the category of encoders),
850−-- just like 'review' produces a function @b -> a@. This is because 'Prism's extract values, in a way that might
851−-- fail, in their forward direction and inject values, in a way that cannot fail, in their reverse direction;
852−-- whereas 'Encoder's encode, which cannot fail, in their forward direction, and decode, which can fail, in their
853−-- reverse direction. In short @reviewEncoder (f . g) = reviewEncoder g . reviewEncoder f@.
854−reviewEncoder :: (Applicative check, MonadError Text parse) => Prism' b a -> Encoder check parse a b
830+prismEncoder :: (Applicative check, MonadError Text parse) => Prism' b a -> Encoder check parse a b
855−reviewEncoder p = unsafeMkEncoder $ EncoderImpl
831+prismEncoder p = unsafeMkEncoder $ EncoderImpl
856− { _encoderImpl_encode = review p
832+ { _encoderImpl_encode = (^. re p)
857 , _encoderImpl_decode = \r -> case r ^? p of
833 , _encoderImpl_decode = \r -> case r ^? p of
858 Just a -> pure a
834 Just a -> pure a
859− Nothing -> throwError "reviewEncoder: value is not present in the prism"
835+ Nothing -> throwError "prismEncoder: value is not present in the prism"
862-- | A URL path and query string, in which trailing slashes don't matter in the path
838-- | A URL path and query string, in which trailing slashes don't matter in the path
@@ -994,9 +970,9 @@ obeliskRouteSegment r appRouteSegment = case r of
994-- be combined with other such segment encoders before 'pathComponentEncoder' turns it into a proper 'Encoder'.
970-- be combined with other such segment encoders before 'pathComponentEncoder' turns it into a proper 'Encoder'.
995resourceRouteSegment :: (MonadError Text check, MonadError Text parse) => ResourceRoute a -> SegmentResult check parse a
971resourceRouteSegment :: (MonadError Text check, MonadError Text parse) => ResourceRoute a -> SegmentResult check parse a
996resourceRouteSegment = \case
972resourceRouteSegment = \case
997− ResourceRoute_Static -> PathSegment "static" pathOnlyEncoderIgnoringQuery
973+ ResourceRoute_Static -> PathSegment "static" $ pathOnlyEncoderIgnoringQuery
998− ResourceRoute_Ghcjs -> PathSegment "ghcjs" pathOnlyEncoder
974+ ResourceRoute_Ghcjs -> PathSegment "ghcjs" $ pathOnlyEncoder
999− ResourceRoute_JSaddleWarp -> PathSegment "jsaddle" jsaddleWarpRouteEncoder
975+ ResourceRoute_JSaddleWarp -> PathSegment "jsaddle" $ jsaddleWarpRouteEncoder
1000 ResourceRoute_Version -> PathSegment "version" $ unitEncoder mempty
976 ResourceRoute_Version -> PathSegment "version" $ unitEncoder mempty
1002data JSaddleWarpRoute :: * -> * where
978data JSaddleWarpRoute :: * -> * where
@@ -1008,7 +984,7 @@ jsaddleWarpRouteEncoder :: (MonadError Text check, MonadError Text parse) => Enc
1008jsaddleWarpRouteEncoder = pathComponentEncoder $ \case
984jsaddleWarpRouteEncoder = pathComponentEncoder $ \case
1009 JSaddleWarpRoute_JavaScript -> PathSegment "jsaddle.js" $ unitEncoder mempty
985 JSaddleWarpRoute_JavaScript -> PathSegment "jsaddle.js" $ unitEncoder mempty
1010 JSaddleWarpRoute_WebSocket -> PathEnd $ unitEncoder mempty
986 JSaddleWarpRoute_WebSocket -> PathEnd $ unitEncoder mempty
1011− JSaddleWarpRoute_Sync -> PathSegment "sync" pathOnlyEncoder
987+ JSaddleWarpRoute_Sync -> PathSegment "sync" $ pathOnlyEncoder
1013instance GShow appRoute => GShow (ObeliskRoute appRoute) where
989instance GShow appRoute => GShow (ObeliskRoute appRoute) where
1014 gshowsPrec prec = \case
990 gshowsPrec prec = \case
@@ -1039,8 +1015,8 @@ someSumEncoder = Encoder $ pure $ EncoderImpl
1040data Void1 :: * -> * where {}
1016data Void1 :: * -> * where {}
1042−instance UniverseSome Void1 where
1018+instance Universe (Some Void1) where
1043− universeSome = []
1019+ universe = []
1045void1Encoder :: (Applicative check, MonadError Text parse) => Encoder check parse (Some Void1) a
1021void1Encoder :: (Applicative check, MonadError Text parse) => Encoder check parse (Some Void1) a
1046void1Encoder = Encoder $ pure $ EncoderImpl
1022void1Encoder = Encoder $ pure $ EncoderImpl
@@ -1052,6 +1028,17 @@ void1Encoder = Encoder $ pure $ EncoderImpl
1052instance GShow Void1 where
1028instance GShow Void1 where
1053 gshowsPrec _ = \case {}
1029 gshowsPrec _ = \case {}
1031+concat <$> mapM deriveRouteComponent
1033+ , ''JSaddleWarpRoute
1037+makePrisms ''ObeliskRoute
1038+makePrisms ''FullRoute
1040+deriveGCompare ''Void1
1055-- | Given a backend route and a checked route encoder, render the route (path
1042-- | Given a backend route and a checked route encoder, render the route (path
1056-- and query string). See 'checkEncoder' for how to produce a checked encoder.
1043-- and query string). See 'checkEncoder' for how to produce a checked encoder.
1057renderBackendRoute
1044renderBackendRoute
@@ -1084,11 +1071,11 @@ readShowEncoder :: (MonadError Text parse, Read a, Show a, Applicative check) =>
1084readShowEncoder = singlePathSegmentEncoder . unsafeTshowEncoder
1071readShowEncoder = singlePathSegmentEncoder . unsafeTshowEncoder
1086integralEncoder :: (MonadError Text parse, Applicative check, Integral a) => Encoder check parse a Integer
1073integralEncoder :: (MonadError Text parse, Applicative check, Integral a) => Encoder check parse a Integer
1087−integralEncoder = reviewEncoder Numeric.Lens.integral
1074+integralEncoder = prismEncoder (Numeric.Lens.integral)
1089pathSegmentEncoder :: (MonadError Text parse, Applicative check, Cons as as a a) =>
1076pathSegmentEncoder :: (MonadError Text parse, Applicative check, Cons as as a a) =>
1090 Encoder check parse (a, (as, b)) (as, b)
1077 Encoder check parse (a, (as, b)) (as, b)
1091−pathSegmentEncoder = first (reviewEncoder _Cons) . disassociate
1078+pathSegmentEncoder = first (prismEncoder _Cons) . disassociate
1093newtype Decoder check parse b a = Decoder { toEncoder :: Encoder check parse a b }
1080newtype Decoder check parse b a = Decoder { toEncoder :: Encoder check parse a b }
@@ -1159,7 +1146,7 @@ pathFieldEncoder fieldEncoder = unsafeEncoder $ do
1159 fieldEncoderPure f = toEncoder (DMap.findWithDefault (error "bad") f fieldEncoderPureMap)
1146 fieldEncoderPure f = toEncoder (DMap.findWithDefault (error "bad") f fieldEncoderPureMap)
1160 pure $ EncoderImpl
1147 pure $ EncoderImpl
1161 { _encoderImpl_encode = \(x, rest) -> execWriter $ do
1148 { _encoderImpl_encode = \(x, rest) -> execWriter $ do
1162− _ <- traverseWithField (\f x_i -> tell (pure $ encode (fieldEncoderPure f) x_i) $> x_i) x
1149+ _ <- traverseWithField (\f x_i -> tell (pure $ encode (fieldEncoderPure f) x_i) *> pure x_i) x
1163 tell rest
1150 tell rest
1164 , _encoderImpl_decode = State.runStateT $ tabulateFieldsA $ \f -> State.get >>= \case
1151 , _encoderImpl_decode = State.runStateT $ tabulateFieldsA $ \f -> State.get >>= \case
1165 [] -> throwError $ T.pack "not enough path components"
1152 [] -> throwError $ T.pack "not enough path components"
@@ -1195,34 +1182,3 @@ byteStringsToPageName p q =
1195 in decode pageNameEncoder' (T.unpack (T.decodeUtf8 p), T.unpack (T.decodeUtf8 q))
1182 in decode pageNameEncoder' (T.unpack (T.decodeUtf8 p), T.unpack (T.decodeUtf8 q))
1197--TODO: decodeURIComponent as appropriate
1184--TODO: decodeURIComponent as appropriate
1200−{-# DEPRECATED isoEncoder "Instead of 'isoEncoder f', use 'viewEncoder f'" #-}
1201−-- | Given a valid 'Iso' from lens, construct an 'Encoder'
1202−isoEncoder :: (Applicative check, Applicative parse) => Iso' a b -> Encoder check parse a b
1203−isoEncoder = viewEncoder
1205−{-# DEPRECATED prismEncoder "Instead of 'prismEncoder f', use 'reviewEncoder f'" #-}
1206−-- | An encoder that only works on the items available via the prism. An error will be thrown in the parse monad
1207−-- if the prism doesn't match.
1209−-- Note that a 'Prism' from @a@ to @b@ will produce an 'Encoder' from @b@ to @a@
1210−-- (i.e. 'prismEncoder' is a contravariant functor from the category of prisms to the category of encoders),
1211−-- just like 'review' produces a function @b -> a@. This is because 'Prism's extract values, in a way that might
1212−-- fail, in their forward direction and inject values, in a way that cannot fail, in their reverse direction;
1213−-- whereas 'Encoder's encode, which cannot fail, in their forward direction, and decode, which can fail, in their
1214−-- reverse direction. In short @prismEncoder (f . g) = prismEncoder g . prismEncoder f@.
1215−prismEncoder :: (Applicative check, MonadError Text parse) => Prism' b a -> Encoder check parse a b
1216−prismEncoder = reviewEncoder
1219−concat <$> mapM deriveRouteComponent
1221− , ''JSaddleWarpRoute
1225−makePrisms ''ObeliskRoute
1226−makePrisms ''FullRoute
1228−deriveGCompare ''Void1