Hi
I am currently porting one of the projects I used to learn Elm from 0.18 to 0.19, it has mostly been a breeze, but I have ran into one problem.
In my application I had got some help form the slack to make a URL parser that would take the “rest” of a given URL after a keyword and give it pack as a list of strings:
For example, In the given URL, everything after album belongs together, and should be given as a list:
example.com/#/album/content/root/index.json
So we will have “album” and [“content”, “root”, “index.json”]
This way I could pass the list as an argument to the album page which then new where to get the data it needed.
The solution I had was a recursive URL parse “builder” with a max depth that would sort this out for me. For credits sake, I basically got help with the whole ting on slack, and tried to understand it.
The code looks like this, and works in 0.18:
In the oneOf:
UrlParser.map (Album << String.join "/") (s "album" </> rest)
And the parser:
rest : UrlParser.Parser (List String -> a) a
rest =
restHelp 10
restHelp : Int -> UrlParser.Parser (List String -> a) a
restHelp maxDepth =
if maxDepth < 1 then
UrlParser.map [] UrlParser.top
else
UrlParser.oneOf
[ UrlParser.map [] UrlParser.top
, UrlParser.map (::) (UrlParser.string </> restHelp (maxDepth - 1))
]
I have rewritten the function to use elm/url, and now it looks like this:
rest : Parser.Parser (List String -> a) a
rest =
restHelp 10
restHelp : Int -> Parser.Parser (List String -> a) a
restHelp maxDepth =
if maxDepth < 1 then
Parser.map [] Parser.top
else
Parser.oneOf
[ Parser.map [] Parser.top
, Parser.map (\str li -> str :: li) (Parser.string </> restHelp (maxDepth - 1))
]
This however does not seem to work, and I get a type mismatch that I cannot figure out:
------------------- src/Data/Url.elm
The 2nd element of this list does not match all the previous elements:
51| [ Parser.map [] Parser.top
52|> , Parser.map (\str li -> str :: li) (Parser.string </> restHelp (maxDepth - 1))
53| ]
This `map` call produces:
Parser.Parser (a -> c) c
But all the previous elements in the list are:
Parser.Parser (List a -> c) c
-- TYPE MISMATCH ---------------------------------------------- src/Data/Url.elm
The 2nd argument to `map` is not what I expect:
52| , Parser.map (\str li -> str :: li) (Parser.string </> restHelp (maxDepth - 1))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This argument is:
Parser.Parser (String -> List String -> a) a
But `map` needs the 2nd argument to be:
Parser.Parser (String -> List String -> List String) a
Does anyone have any suggestions on how to solve this? I am up for a different solution also as I feel like it might be a bit hacky.
I was thinking about the though of something that parse strings until it hits a json file with a custom encoder; but cannot seem to get that to work either…
For example ending with a match of:
json : Parser.Parser (String -> a) a
json =
Parser.custom "JSON_FILE" <|
\segment ->
if String.endsWith ".json" segment then
Just segment
else
Nothing
Thank you.