Advertisement
Guest User

Untitled

a guest
May 6th, 2016
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.05 KB | None | 0 0
  1. {-# LANGUAGE OverloadedStrings #-}
  2.  
  3. module Server where
  4.  
  5. import Types
  6.  
  7. import Control.Concurrent (myThreadId)
  8. import Control.Monad.IO.Class (liftIO)
  9. import Control.Monad.Trans.Either (EitherT, left)
  10. import Data.IORef (IORef, atomicModifyIORef', readIORef)
  11. import Data.List ((\\), sortBy)
  12. import Data.Ord (comparing)
  13. import qualified Data.IntMap.Lazy as IM (IntMap, elems, insert, keys, lookup, member)
  14. import Servant ((:<|>)(..), Proxy(..), Server, ServantErr, err404, errBody)
  15.  
  16.  
  17. vehicleAPI :: Proxy VehicleAPI
  18. vehicleAPI = Proxy
  19.  
  20.  
  21. server :: IORef (IM.IntMap Vehicle) -> Server VehicleAPI
  22. server ref = getAllVehicles
  23. :<|> getVehicleById
  24. :<|> postVehicle
  25. :<|> putVehicle
  26. -----
  27. :<|> getIssuesById
  28. :<|> putIssues
  29. where
  30. getAllVehicles :: EitherT ServantErr IO [Vehicle]
  31. getAllVehicles = do
  32. liftIO $ print =<< myThreadId
  33. IM.elems <$> liftIO (readIORef ref)
  34.  
  35. getVehicleById :: Int -> EitherT ServantErr IO Vehicle
  36. getVehicleById i = maybe notFound return =<< IM.lookup i <$> liftIO (readIORef ref)
  37.  
  38. notFound :: EitherT ServantErr IO a
  39. notFound = left err404 { errBody = "Vehicle ID not found." }
  40.  
  41. postVehicle :: Vehicle -> EitherT ServantErr IO Vehicle
  42. postVehicle v = liftIO $ atomicModifyIORef' ref insertIntoTbl
  43. where
  44. insertIntoTbl :: IM.IntMap Vehicle -> (IM.IntMap Vehicle, Vehicle)
  45. insertIntoTbl tbl = let newUniqueId = head . ([0..] \\) $ IM.keys tbl
  46. tbl' = IM.insert newUniqueId v tbl
  47. in (tbl', v)
  48.  
  49. putVehicle :: Int -> Vehicle -> EitherT ServantErr IO Vehicle
  50. putVehicle i v = putHelper f
  51. where
  52. f :: IM.IntMap Vehicle -> (IM.IntMap Vehicle, Maybe Vehicle)
  53. f tbl | i `IM.member` tbl = let tbl' = IM.insert i v tbl
  54. in (tbl', Just v)
  55. | otherwise = (tbl, Nothing)
  56.  
  57. putHelper :: (IM.IntMap Vehicle -> (IM.IntMap Vehicle, Maybe a)) -> EitherT ServantErr IO a
  58. putHelper f = maybe notFound return =<< liftIO (atomicModifyIORef' ref f)
  59.  
  60. -----
  61.  
  62. getIssuesById :: Int -> Maybe SortBy -> EitherT ServantErr IO [Issue]
  63. getIssuesById i msb = do
  64. unsorted <- issues <$> getVehicleById i
  65. return . maybe unsorted (sortIssues unsorted) $ msb
  66. where
  67. sortIssues :: [Issue] -> SortBy -> [Issue]
  68. sortIssues is sb = case sb of ByType -> sortHelper issueType is
  69. ByPriority -> sortHelper priority is
  70.  
  71. sortHelper :: (Ord a) => (Issue -> a) -> [Issue] -> [Issue]
  72. sortHelper = sortBy . comparing
  73.  
  74. putIssues :: Int -> [Issue] -> EitherT ServantErr IO [Issue]
  75. putIssues i is = putHelper f
  76. where
  77. f :: IM.IntMap Vehicle -> (IM.IntMap Vehicle, Maybe [Issue])
  78. f tbl = maybe (tbl, Nothing) found $ IM.lookup i tbl
  79. where
  80. found :: Vehicle -> (IM.IntMap Vehicle, Maybe [Issue])
  81. found v = let v' = v { issues = is }
  82. tbl' = IM.insert i v' tbl
  83. in (tbl', Just is)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement