1{-# LANGUAGE MultiParamTypeClasses #-}
2{-# LANGUAGE FunctionalDependencies #-}
3{-# LANGUAGE DataKinds #-}
4{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE ScopedTypeVariables #-}
6{-# LANGUAGE TemplateHaskell #-}
7module Servant.API.QQ where
9import Control.Applicative
10import Data.List.Split (splitOn)
11import Data.Maybe (mapMaybe)
12import Language.Haskell.TH.Quote
13import Language.Haskell.TH
16import Servant.API.Capture
18import Servant.API.Post
20import Servant.API.Delete
21import Servant.API.QueryParam
22import Servant.API.ReqBody
24import Servant.API.Alternative
26class ExpSYM repr' repr | repr -> repr', repr' -> repr where
27 lit :: String -> repr' -> repr
28 capture :: String -> String -> repr -> repr
29 reqBody :: String -> repr -> repr
30 queryParam :: String -> String -> repr -> repr
31 conj :: repr' -> repr -> repr
33 post :: String -> repr
35 delete :: String -> repr
39(>:) :: Type -> Type -> Type
43instance ExpSYM Type Type where
44 lit name r = LitT (StrTyLit name) >: r
45 capture name typ r = AppT (AppT (ConT ''Capture) (LitT (StrTyLit name)))
46 (ConT $ mkName typ) >: r
47 reqBody typ r = AppT (ConT ''ReqBody) (ConT $ mkName typ) >: r
48 queryParam name typ r = AppT (AppT (ConT ''QueryParam) (LitT (StrTyLit name)))
49 (ConT $ mkName typ) >: r
50 conj x = AppT (AppT (ConT ''(:>)) x)
51 get typ = AppT (ConT ''Get) (ConT $ mkName typ)
52 post typ = AppT (ConT ''Post) (ConT $ mkName typ)
53 put typ = AppT (ConT ''Put) (ConT $ mkName typ)
54 delete "()" = ConT ''Delete
55 delete _ = error "Delete does not return a request body"
57readEntry :: ExpSYM r r => [String] -> Maybe r
59readEntry (met:xs:typ) = case met of
64 x -> error $ "Unknown method: " ++ x
65 where typ' = splitOn "->" $ concat typ
67 [] -> readEntry' xs $ m "()"
68 [rsp] -> readEntry' xs $ m rsp
69 (rqbd:[rsp]) -> readEntry' xs $ reqBody rqbd $ m rsp
70 _ -> error "Only functions of one argument allowed!"
71readEntry x = error $ "Wrong number of elems in line: " ++ show x
73readEntry' :: ExpSYM r r => String -> r -> Maybe r
74readEntry' [] _ = Nothing
75readEntry' xs r = Just $ foldr1 (.) (tRepr <$> splitOn "/" xs) r
77 tRepr y | [x] <- splitOn ":" y = lit x
78 | a:[b] <- splitOn ":" y = case headMay a of
79 Just '?' -> queryParam (tail a) b
81 Nothing -> error "Expecting something after '/'"
82 | otherwise = error "Only one ':' per section"
84readAll :: String -> Type
85readAll s = foldr1 union $ mapMaybe readEntry $ words <$> lines s
86 where union :: Type -> Type -> Type
87 union a = AppT (AppT (ConT ''(:<|>)) a)
90sitemap = QuasiQuoter { quoteExp = undefined
91 , quotePat = undefined
92 , quoteType = return . readAll
93 , quoteDec = undefined
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list