Skip to content

Instantly share code, notes, and snippets.

@benkolera
Last active February 25, 2019 00:18
Show Gist options
  • Save benkolera/0fd7bf9a57775ab01b8a7ec83f5fb755 to your computer and use it in GitHub Desktop.
Save benkolera/0fd7bf9a57775ab01b8a7ec83f5fb755 to your computer and use it in GitHub Desktop.
Need to figure out how to get this route to work...
-- The problem is that I need to model the following routes:
-- * /profile/:username
-- * /profile/:username/favourites
--
-- And I'm a little stuck and I'm not sure whether it is my encoding of the routes,
-- that I'm missing an important combinator or Obelisk just doesn't handle this yet.
newtype Username = Username { unUsername :: Text } deriving (Eq, Ord, Show)
makeWrapped ''Username
data FrontendRoute :: * -> * where
FrontendRoute_Home :: FrontendRoute ()
FrontendRoute_Profile :: FrontendRoute (Username, Maybe (R ProfileRoute))
data ProfileRoute :: * -> * where
ProfileRoute_Favourites :: ProfileRoute ()
backendRouteEncoder
:: Encoder (Either Text) Identity (R (Sum BackendRoute (ObeliskRoute FrontendRoute))) PageName
backendRouteEncoder = handleEncoder (const (InL BackendRoute_Missing :/ ())) $
pathComponentEncoder $ \case
InL backendRoute -> case backendRoute of
BackendRoute_Missing -> PathSegment "missing" $ unitEncoder mempty
InR obeliskRoute -> obeliskRouteSegment obeliskRoute $ \case
FrontendRoute_Home -> PathEnd $ unitEncoder mempty
FrontendRoute_Profile -> PathSegment "profile" $ unicorn
unicorn
:: (MonadError Text parse, check ~ parse)
=> Encoder check parse (Username, Maybe (R ProfileRoute)) PageName
unicorn = segmentParam unwrappedEncoder profileRMayEnc -- This may be nonsensical. Follow reasoning below
where
-- I know how to do these two things separately! But it doesn't feel like this is the way to go
-- because both encoders would encode into query params and could clash horribly
usernameEnc :: (Applicative check, MonadError Text parse) => Encoder check parse Username PageName
usernameEnc = singlePathSegmentEncoder . unwrappedEncoder
profileRMayEnc :: (MonadError Text check, check ~ parse) => Encoder check parse (Maybe (R ProfileRoute)) PageName
profileRMayEnc = maybeEncoder (unitEncoder mempty) $ pathComponentEncoder $ \case
ProfileRoute_Favourites -> PathEnd $ unitEncoder mempty
-- It feels like you want something that can peel a pathPart off and handle the rest as a sub
-- like the maybeEncoder, but it's a 1 or more encoder that doesn't lose the params.
segmentParam
:: MonadError Text parse
=> Encoder check parse a Text
-> Encoder check parse b PageName
-> Encoder check parse (a,b) PageName
segmentParam = undefined
-- But I don't know whether this makes sense or could be implemented lawfully
-- This kinda looks like chainEncoder, but chainEncoder doesn't feel like it
-- I may just missing the implication of an important instance on Encoder
-- * Category (Encoder check parse)
-- * Associative (Encoder check parse) (,)
-- * Monoidal (Encoder check parse) (,)
-- * Cat.Functor f (Encoder check parse) (Encoder check parse)
-- * PFunctor (,) (Encoder check parse) (Encoder check parse)
-- * QFunctor (,) (Encoder check parse) (Encoder check parse)
-- * Bifunctor (,) (Encoder check parse) (Encoder check parse)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment