Url Parsing in Idris
Here’s the translation of the Go URL parsing example to Idris:
Our URL parsing program demonstrates how to parse URLs in Idris. URLs provide a uniform way to locate resources.
import Data.String
import Data.List
import Data.Maybe
-- Define a record to hold URL components
record URL where
constructor MkURL
scheme : String
user : Maybe (String, Maybe String)
host : String
port : Maybe String
path : String
query : String
fragment : Maybe String
-- Parse a URL string into a URL record
parseURL : String -> Maybe URL
parseURL s = do
let parts = split (== ':') s
scheme <- head' parts
rest <- tail' parts >>= head'
let withoutScheme = dropWhile (== '/') rest
let (authority, pathAndRest) = break (== '/') withoutScheme
let (userInfo, hostPort) = break (== '@') authority
let (host, maybePort) = break (== ':') (if hostPort == "" then userInfo else hostPort)
let (path, queryAndFragment) = break (== '?') pathAndRest
let (query, fragment) = break (== '#') (if queryAndFragment == "" then "" else tail queryAndFragment)
pure $ MkURL scheme (parseUserInfo userInfo) host (tailMay maybePort)
("/" ++ path) query (nullToNothing fragment)
where
parseUserInfo : String -> Maybe (String, Maybe String)
parseUserInfo "" = Nothing
parseUserInfo s =
let (user, pass) = break (== ':') s
in Just (user, tailMay pass)
tailMay : String -> Maybe String
tailMay "" = Nothing
tailMay s = Just (tail s)
nullToNothing : String -> Maybe String
nullToNothing "" = Nothing
nullToNothing s = Just s
-- Main function to demonstrate URL parsing
main : IO ()
main = do
let s = "postgres://user:pass@host.com:5432/path?k=v#f"
case parseURL s of
Nothing -> putStrLn "Failed to parse URL"
Just u -> do
putStrLn $ "Scheme: " ++ u.scheme
putStrLn $ "User Info: " ++ show u.user
putStrLn $ "Host: " ++ u.host
putStrLn $ "Port: " ++ show u.port
putStrLn $ "Path: " ++ u.path
putStrLn $ "Query: " ++ u.query
putStrLn $ "Fragment: " ++ show u.fragment
This Idris code defines a URL
record to hold the components of a URL, and a parseURL
function to parse a URL string into this record. The main
function demonstrates how to use this parser.
To run the program:
$ idris url_parsing.idr -o url_parsing
$ ./url_parsing
Scheme: postgres
User Info: Just ("user", Just "pass")
Host: host.com
Port: Just "5432"
Path: /path
Query: k=v
Fragment: Just "f"
This output shows the different pieces extracted from the URL. Note that Idris, being a purely functional language, handles errors and optional values using Maybe
types, which is different from Go’s approach of returning error values.
Also, Idris doesn’t have built-in networking libraries like Go’s net/url
, so we’ve implemented a basic URL parser from scratch. In a real-world scenario, you might want to use a more robust parsing library or implement more comprehensive error handling and validation.