module Main %default total data Matcher = MDirectory String Matcher | MCapture Matcher | End data Commands = Capture infixr 8 // interface Matchable a where (//) : a -> Matcher -> Matcher Matchable String where x // m = MDirectory x m Matchable Commands where Capture // m = MCapture m HandlerType : Matcher -> Type HandlerType (MDirectory s m) = HandlerType m HandlerType (MCapture m) = String -> HandlerType m HandlerType End = String Handler : Type Handler = (m : Matcher ** HandlerType m) dispatch : (handlers : List Handler) -> String -> Maybe String dispatch [] _ = Nothing dispatch handlers path = go handlers components where components : List String components = filter (/="") (split (=='/') path) go : List Handler -> List String -> Maybe String go [] cs = Nothing go ((m ** f) :: hs) cs = let next = go hs cs in case m of MDirectory dir matcher => case cs of (c :: cs') => if c == dir then go ((matcher ** f) :: hs) cs' else next _ => next MCapture matcher => case cs of (c :: cs') => go ((matcher ** f c) :: hs) cs' _ => next End => Just f helloHandler : String -> String -> String helloHandler firstName lastName = "Hello, " ++ firstName ++ " " ++ lastName weatherHandler : String -> String weatherHandler place = "The weather in " ++ place ++ " is cold." handlers : List Handler handlers = [ ("hello" // Capture // Capture // End ** helloHandler) , ("weather" // Capture // End ** weatherHandler) ] main : IO () main = do putStrLn (fromMaybe "failed" $ dispatch handlers "hello/Bob/Sunshine") putStrLn (fromMaybe "failed" $ dispatch handlers "weather/New York")