I have a question about the routing-duplex library that is so well described here. I am trying to combine two sum types [sum, print, parse, /, Generic, root, noArgs are all imported from Routing.Duplex...]:
data Language = French | English
languageCodec :: RouteDuplex' Language
languageCodec =
sum
{ "French": "fr" / noArgs
, "English": "en" / noArgs
}
derive instance genericLanguage :: Generic Language _
derive instance eqLanguage :: Eq Language
derive instance ordLanguage :: Ord Language
data Page
= Main
| Contact
| About
derive instance genericPage :: Generic Page _
derive instance eqPage :: Eq Page
derive instance ordPage :: Ord Page
pageCodec :: RouteDuplex' Page
pageCodec =
sum
{ "Main": noArgs
, "Contact": "contact" / noArgs
, "About": "about" / noArgs
}
Thanks for the answer. I read through the GitHub issue and finally understood that really the use case of sum is not what I am using it for. A simple two-way mapping from String to a custom type should be enough. I was able to work around it with as:
data Route
= Route (Maybe Language) (Maybe Page)
derive instance genericRoute :: Generic Route _
derive instance eqRoute :: Eq Route
routeCodec :: RouteDuplex' Route
routeCodec =
root
$ sum
{ "Route": optional (languageCodec segment) / optional (pageCodec segment)}
data Language = French | English
derive instance eqLanguage :: Eq Language
languageCodec :: RouteDuplex' String -> RouteDuplex' Language
languageCodec = RD.as languageToRouteString routeStringToLanguage
where
languageToRouteString :: Language -> String
languageToRouteString = case _ of
French -> "fr"
English -> "en"
routeStringToLanguage :: String -> Either String Language
routeStringToLanguage = case _ of
"fr" -> Right French
"en" -> Right English
_ -> Right English
data Page
= Main | Contact | About
derive instance eqPage :: Eq Page
pageCodec :: RouteDuplex' String -> RouteDuplex' Page
pageCodec = RD.as pageToRouteString routeStringToPage
where
pageToRouteString :: Page -> String
pageToRouteString = case _ of
Main -> "index"
Contact -> "contact"
About -> "about"
routeStringToPage :: String -> Either String Page
routeStringToPage = case _ of
"index" -> Right Main
"contact" -> Right Contact
"about" -> Right About
_ -> Right Main
It works. I added optional and a default case to the combined parser to reroute wrong routes to Main - not sure if that’s a good idea. Happy about suggestions how to improve this.