git.iko.soy/typeable/servant-reflex
on master help sign in
added support for diacratic chars in json text, bumped servant upper bounds
commitd72d6a7decd7f202b0b9abe9cc2ea8fb3f5b98a2 authorSchell Scivally <efsubenovex@gmail.com> dateMon 27 Feb 2017, 11:46 (10 years ago) parent183d8db
11 files changed+191−108
.gitignore+1 deps/servant+1−1 exec/API.hs+28−4 exec/Example.hs+15−4 overrides-ghc.nix+30−2 overrides.nix+21 servant-reflex.cabal+4−3 src/Servant/Common/Req.hs+1−7 src/Servant/Reflex.hs+62−67 testserver/Main.hs+17−9 testserver/testserver.cabal+11−11
.gitignore+1
@@ -6,3 +6,4 @@ log
66*.webapp
77*.stats
88out
9+reflex-platform
deps/servant+1−1

Submodule changed.

exec/API.hs+28−4
@@ -1,10 +1,32 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE TypeOperators #-}
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+{-# LANGUAGE TypeOperators #-}
34
45module API where
56
6−import Data.Text (Text)
7−import Servant.API
7+import Data.Aeson
8+import Data.Aeson.Types (typeMismatch)
9+import Data.Text (Text)
10+import Servant.API
11+
12+newtype Question = Question { unQuestion :: Text } deriving (Show)
13+
14+instance ToJSON Question where
15+ toJSON (Question txt) = object ["question" .= txt]
16+
17+instance FromJSON Question where
18+ parseJSON (Object v) = Question <$> v .: "question"
19+ parseJSON x = typeMismatch "Couldn't find key 'question'" x
20+
21+newtype Answer = Answer { unAnswer :: Text } deriving (Show)
22+
23+instance ToJSON Answer where
24+ toJSON (Answer txt) = object ["answer" .= txt]
25+
26+instance FromJSON Answer where
27+ parseJSON (Object v) = Answer <$> v .: "answer"
28+ parseJSON x = typeMismatch "Couldn't find key 'answer'" x
29+
830
931-- | API spec for server, client, and docs
1032type API = "getunit" :> Get '[JSON] ()
@@ -16,6 +38,8 @@ type API = "getunit" :> Get '[JSON] ()
1638 :<|> "double" :> ReqBody '[JSON] Double
1739 :> Post '[JSON] Double
1840 :<|> "a" :> "b" :> QueryFlag "gusto" :> Get '[JSON] Text
41+ :<|> "qna" :> ReqBody '[JSON] Question
42+ :> Post '[JSON] Answer
1943 :<|> Raw
2044
2145type GET = Get '[JSON] ()
exec/Example.hs+15−4
@@ -42,7 +42,7 @@ run = do
4242 el "br" (return ())
4343
4444 -- Name the computed API client functions
45− let (getUnit :<|> getInt :<|> sayhi :<|> dbl :<|> multi :<|> doRaw) =
45+ let (getUnit :<|> getInt :<|> sayhi :<|> dbl :<|> multi :<|> qna :<|> doRaw) =
4646 client api (Proxy :: Proxy m) url
4747
4848 elClass "div" "demo-group" $ do
@@ -89,11 +89,11 @@ run = do
8989 elClass "div" "demo-group" $ do
9090 text "A Double to double"
9191 el "br" $ return ()
92− dblinp <- fmap value $ divClass "double-input" $ textInput def
93− dblBtn <- divClass "double-button" $ button "Double it"
92+ dblinp <- fmap value $ divClass "double-input" $ textInput def
93+ dblBtn <- divClass "double-button" $ button "Double it"
9494 dblResp <- dbl (fmap (note "read failure" . readMaybe . T.unpack) $
9595 dblinp) dblBtn
96− divClass "double-errors" $ dynText =<<
96+ divClass "double-errors" $ dynText =<<
9797 holdDyn "(no errors)" (fmapMaybe reqFailure dblResp)
9898 el "br" (return ())
9999 divClass "double-result" $ el "p" $ dynText =<<
@@ -109,6 +109,17 @@ run = do
109109 fmapMaybe reqSuccess $
110110 multiResp)
111111
112+ el "br" $ return ()
113+
114+ elClass "div" "demo-group" $ do
115+ text "JSON Unicode encoding test"
116+ txt <- value <$> textInput def
117+ ev <- button "Question"
118+ let dQ = Right . Question <$> traceDyn "will send: " txt
119+ rr <- qna dQ ev
120+ el "p" $
121+ dynText =<< holdDyn "No Answer" (unAnswer <$> fmapMaybe reqSuccess rr)
122+
112123showXhrResponse :: XhrResponse -> Text
113124showXhrResponse (XhrResponse stat stattxt rbmay rtmay respHeaders) =
114125 T.unlines ["stat: " <> tShow stat
overrides-ghc.nix+30−2
@@ -1,10 +1,16 @@
11{ reflex-platform, ... }:
2−let
2+let
33 pkgs = import <nixpkgs> {};
44 c2n = reflex-platform.cabal2nixResult;
55in reflex-platform.ghc.override {
66 overrides = self: super: {
7− servant-snap = pkgs.haskell.lib.dontCheck (self.callPackage (c2n deps/servant-snap) {});
7+ #servant-snap = pkgs.haskell.lib.dontCheck (self.callPackage (c2n deps/servant-snap) {});
8+ servant-snap = pkgs.haskell.lib.dontCheck (self.callPackage (c2n (pkgs.fetchFromGitHub {
9+ owner = "schell";
10+ repo = "servant-snap";
11+ rev = "6732e7eebebcb25162924ba3d25fb37647d0749a";
12+ sha256 = "07dh8ab1ffv5k6xik5m7zz6l3dcg6n1qbh8ndjnci0z2rim22asw";
13+ })) {});
814 snap = pkgs.haskell.lib.dontCheck (self.callPackage (c2n deps/servant-snap/deps/snap) {});
915 snap-server = pkgs.haskell.lib.dontCheck (self.callPackage (c2n deps/servant-snap/deps/snap/deps/snap-server) {});
1016 io-streams = pkgs.haskell.lib.dontCheck (self.callPackage (c2n deps/servant-snap/deps/snap/deps/io-streams) {});
@@ -13,6 +19,28 @@ in reflex-platform.ghc.override {
1319 xmlhtml = pkgs.haskell.lib.dontCheck (self.callPackage (c2n deps/servant-snap/deps/snap/deps/xmlhtml) {});
1420 snap-core = pkgs.haskell.lib.dontCheck (self.callPackage (c2n deps/servant-snap/deps/snap/deps/snap-core) {});
1521 servant = pkgs.haskell.lib.dontCheck (self.callPackage (c2n deps/servant/servant) {});
22+ Glob = pkgs.haskell.lib.dontCheck super.Glob;
23+ natural-transformation = self.callPackage (
24+ { mkDerivation, base, containers, fetchgit, quickcheck-instances
25+ , stdenv, tasty, tasty-quickcheck
26+ }:
27+ mkDerivation {
28+ pname = "natural-transformation";
29+ version = "0.4";
30+ src = fetchgit {
31+ url = "https://github.com/ku-fpg/natural-transformation";
32+ sha256 = "0xbnnxbf5ydszbhf7h5ra3mrqy4mcyqc3zb2k8bwm1zyqrz6v0fs";
33+ rev = "b1200c09dcafd034e32846413913b74735c8ba56";
34+ };
35+ libraryHaskellDepends = [ base ];
36+ testHaskellDepends = [
37+ base containers quickcheck-instances tasty tasty-quickcheck
38+ ];
39+ homepage = "https://github.com/ku-fpg/natural-transformation";
40+ description = "A natural transformation package";
41+ license = stdenv.lib.licenses.bsd3;
42+ }
43+ ) {};
1644 http-api-data = pkgs.haskell.lib.dontCheck (self.callPackage (c2n deps/http-api-data) {});
1745 };
1846}
overrides.nix+21
@@ -10,5 +10,26 @@ reflex-platform.ghcjs.override {
1010 overrides = self: super: {
1111 servant = dontCheck (self.callPackage (cabal2nixResult deps/servant/servant) {});
1212 http-api-data = dontCheck (self.callPackage (cabal2nixResult deps/http-api-data) {});
13+ natural-transformation = self.callPackage (
14+ { mkDerivation, base, containers, fetchgit, quickcheck-instances
15+ , stdenv, tasty, tasty-quickcheck
16+ }:
17+ mkDerivation {
18+ pname = "natural-transformation";
19+ version = "0.4";
20+ src = fetchgit {
21+ url = "https://github.com/ku-fpg/natural-transformation";
22+ sha256 = "0xbnnxbf5ydszbhf7h5ra3mrqy4mcyqc3zb2k8bwm1zyqrz6v0fs";
23+ rev = "b1200c09dcafd034e32846413913b74735c8ba56";
24+ };
25+ libraryHaskellDepends = [ base ];
26+ testHaskellDepends = [
27+ base containers quickcheck-instances tasty tasty-quickcheck
28+ ];
29+ homepage = "https://github.com/ku-fpg/natural-transformation";
30+ description = "A natural transformation package";
31+ license = stdenv.lib.licenses.bsd3;
32+ }
33+ ) {};
1334 };
1435}
servant-reflex.cabal+4−3
@@ -1,5 +1,5 @@
11Name: servant-reflex
2−Version: 0.2
2+Version: 0.3.0
33Synopsis: Servant reflex API generator
44Description: Servant reflex API generator
55License: AllRightsReserved
@@ -21,6 +21,7 @@ library
2121
2222 hs-source-dirs: src
2323 build-depends:
24+ aeson,
2425 base >= 4.8 && < 4.10,
2526 bytestring >= 0.10 && < 0.11,
2627 case-insensitive >= 1.2.0.4 && < 1.3,
@@ -35,7 +36,7 @@ library
3536 reflex >= 0.5 && < 0.6,
3637 reflex-dom == 0.4 && < 0.5,
3738 safe >= 0.3.9 && < 0.4,
38− servant >= 0.5 && < 0.9,
39+ servant >= 0.8 && < 0.11,
3940 string-conversions >= 0.4 && < 0.5,
4041 text >= 1.2 && < 1.3,
4142 transformers >= 0.4 && < 0.6
@@ -45,7 +46,7 @@ library
4546 default-language: Haskell2010
4647
4748executable example
48− build-depends: reflex, servant-reflex, base, scientific, servant, reflex-dom, text
49+ build-depends: aeson, reflex, servant-reflex, base, scientific, servant, reflex-dom, text
4950 default-language: Haskell2010
5051 main-is: Example.hs
5152 other-modules: API
src/Servant/Common/Req.hs+1−7
@@ -210,15 +210,9 @@ performRequest reqMeth req reqHost trigger = do
210210
211211 return (resps, badReqs)
212212
213−#ifdef ghcjs_HOST_OS
214−type XhrPayload = String
215−bytesToPayload :: BL.ByteString -> XhrPayload
216−bytesToPayload = BL.unpack
217−#else
218213type XhrPayload = T.Text
219214bytesToPayload :: BL.ByteString -> XhrPayload
220−bytesToPayload = T.pack . BL.unpack
221−#endif
215+bytesToPayload = TE.decodeUtf8 . BL.toStrict
222216
223217performRequestNoBody :: forall t m .(SupportsServantReflex t m)
224218 => Text
src/Servant/Reflex.hs+62−67
@@ -1,16 +1,16 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE DataKinds #-}
3−{-# LANGUAGE FlexibleContexts #-}
4−{-# LANGUAGE FlexibleInstances #-}
5−{-# LANGUAGE InstanceSigs #-}
6−{-# LANGUAGE OverloadedStrings #-}
7−{-# LANGUAGE PolyKinds #-}
8−{-# LANGUAGE ScopedTypeVariables #-}
9−{-# LANGUAGE TupleSections #-}
10−{-# LANGUAGE TypeFamilies #-}
11−{-# LANGUAGE TypeOperators #-}
12−{-# LANGUAGE UndecidableInstances #-}
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE InstanceSigs #-}
136{-# LANGUAGE MultiParamTypeClasses #-}
7+{-# LANGUAGE OverloadedStrings #-}
8+{-# LANGUAGE PolyKinds #-}
9+{-# LANGUAGE ScopedTypeVariables #-}
10+{-# LANGUAGE TupleSections #-}
11+{-# LANGUAGE TypeFamilies #-}
12+{-# LANGUAGE TypeOperators #-}
13+{-# LANGUAGE UndecidableInstances #-}
1414
1515-- #include "overlapping-compat.h"
1616-- | This module provides 'client' which can automatically generate
@@ -25,42 +25,42 @@ module Servant.Reflex
2525
2626-------------------------------------------------------------------------------
2727import Control.Applicative
28−import Data.Monoid ((<>))
29−import qualified Data.Set as Set
30−import qualified Data.Text.Encoding as E
31−import Data.CaseInsensitive (mk)
32−import Data.Proxy (Proxy (..))
33−import qualified Data.Map as Map
34−import Data.Text (Text)
35−import qualified Data.Text as T
36−import GHC.TypeLits (KnownSymbol, symbolVal)
37−import Servant.API ((:<|>)(..),(:>), BasicAuth,
38− BasicAuthData, BuildHeadersTo(..),
39− Capture, contentType, Header,
40− Headers(..), HttpVersion, IsSecure,
41− MimeRender(..), MimeUnrender,
42− NoContent, QueryFlag, QueryParam,
43− QueryParams, Raw, ReflectMethod(..),
44− RemoteHost, ReqBody,
45− ToHttpApiData(..), Vault, Verb)
46−import Servant.Common.BaseUrl (BaseUrl(..), Scheme(..), baseUrlWidget,
47− showBaseUrl,
48− SupportsServantReflex)
49−import Servant.Common.Req (Req, ReqResult(..), QParam(..),
50− QueryPart(..), addHeader, authData,
51− defReq, prependToPathParts,
52− performRequestCT,
53− performRequestNoBody,
54− qParamToQueryPart, reqBody,
55− reqSuccess, reqFailure,
56− reqMethod, respHeaders, response,
57− qParams)
58−import Reflex.Dom (Dynamic, Event, Reflex,
59− XhrRequest(..),
60− XhrResponseHeaders(..),
61− XhrResponse(..), ffor, fmapMaybe,
62− leftmost, performRequestAsync,
63− tagPromptlyDyn )
28+import Data.Aeson (ToJSON, encode)
29+import Data.CaseInsensitive (mk)
30+import qualified Data.Map as Map
31+import Data.Monoid ((<>))
32+import Data.Proxy (Proxy (..))
33+import qualified Data.Set as Set
34+import Data.Text (Text)
35+import qualified Data.Text as T
36+import qualified Data.Text.Encoding as E
37+import Debug.Trace (traceShow)
38+import GHC.TypeLits (KnownSymbol, symbolVal)
39+import Reflex.Dom (Dynamic, Event, Reflex,
40+ XhrRequest (..), XhrResponse (..),
41+ XhrResponseHeaders (..), ffor,
42+ fmapMaybe, leftmost,
43+ performRequestAsync, tagPromptlyDyn)
44+import Servant.API ((:<|>) (..), (:>), BasicAuth,
45+ BasicAuthData, BuildHeadersTo (..),
46+ Capture, Header, Headers (..),
47+ HttpVersion, IsSecure, MimeRender (..),
48+ MimeUnrender, NoContent, QueryFlag,
49+ QueryParam, QueryParams, Raw,
50+ ReflectMethod (..), RemoteHost,
51+ ReqBody, ToHttpApiData (..), Vault,
52+ Verb, contentType)
53+import Servant.Common.BaseUrl (BaseUrl (..), Scheme (..),
54+ SupportsServantReflex, baseUrlWidget,
55+ showBaseUrl)
56+import Servant.Common.Req (QParam (..), QueryPart (..), Req,
57+ ReqResult (..), addHeader, authData,
58+ defReq, performRequestCT,
59+ performRequestNoBody,
60+ prependToPathParts, qParamToQueryPart,
61+ qParams, reqBody, reqFailure,
62+ reqMethod, reqSuccess, respHeaders,
63+ response)
6464
6565-- * Accessing APIs as a Client
6666
@@ -79,7 +79,7 @@ import Reflex.Dom (Dynamic, Event, Reflex,
7979-- > where host = constDyn $ BaseUrl Http "localhost" 8080
8080client :: (HasClient t m layout)
8181 => Proxy layout -> Proxy m -> Dynamic t BaseUrl -> Client t m layout
82−client p q baseurl = clientWithRoute p q defReq baseurl
82+client p q = clientWithRoute p q defReq
8383
8484-- | This class lets us define how each API combinator
8585-- influences the creation of an HTTP request. It's mostly
@@ -118,7 +118,7 @@ instance (SupportsServantReflex t m, ToHttpApiData a, HasClient t m sublayout)
118118 (prependToPathParts p req)
119119 baseurl
120120
121− where p = (fmap . fmap) (toUrlPiece) val
121+ where p = (fmap . fmap) toUrlPiece val
122122
123123-- VERB (Returning content) --
124124instance {-# OVERLAPPABLE #-}
@@ -129,8 +129,8 @@ instance {-# OVERLAPPABLE #-}
129129 Event t () -> m (Event t (ReqResult a))
130130 -- TODO how to access input types here?
131131 -- ExceptT ServantError IO a
132− clientWithRoute Proxy _ req baseurl =
133− performRequestCT (Proxy :: Proxy ct) method req' baseurl
132+ clientWithRoute Proxy _ req =
133+ performRequestCT (Proxy :: Proxy ct) method req'
134134 where method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
135135 req' = req { reqMethod = method }
136136
@@ -142,8 +142,8 @@ instance {-# OVERLAPPING #-}
142142 Event t () -> m (Event t (ReqResult NoContent))
143143 -- TODO: how to access input types here?
144144 -- ExceptT ServantError IO NoContent
145− clientWithRoute Proxy _ req baseurl =
146− performRequestNoBody method req baseurl
145+ clientWithRoute Proxy _ =
146+ performRequestNoBody method
147147 where method = E.decodeUtf8 $ reflectMethod (Proxy :: Proxy method)
148148
149149toHeaders :: BuildHeadersTo ls => ReqResult a -> ReqResult (Headers ls a)
@@ -163,7 +163,7 @@ instance {-# OVERLAPPABLE #-} BuildHeaderKeysTo '[]
163163
164164instance {-# OVERLAPPABLE #-} (BuildHeaderKeysTo xs, KnownSymbol h)
165165 => BuildHeaderKeysTo '[(Header h v) ': xs] where
166− buildHeaderKeysTo _ = (T.pack $ symbolVal (Proxy :: Proxy h)) : buildHeaderKeysTo (Proxy :: Proxy xs)
166+ buildHeaderKeysTo _ = T.pack (symbolVal (Proxy :: Proxy h)) : buildHeaderKeysTo (Proxy :: Proxy xs)
167167
168168-- HEADERS Verb (Content) --
169169-- Headers combinator not treated in fully general case,
@@ -237,8 +237,7 @@ instance HasClient t m sublayout
237237 type Client t m (HttpVersion :> sublayout) =
238238 Client t m sublayout
239239
240− clientWithRoute Proxy q =
241− clientWithRoute (Proxy :: Proxy sublayout) q
240+ clientWithRoute Proxy = clientWithRoute (Proxy :: Proxy sublayout)
242241
243242
244243-- | If you use a 'QueryParam' in one of your endpoints in your API,
@@ -323,7 +322,7 @@ instance (KnownSymbol sym, ToHttpApiData a, HasClient t m sublayout, Reflex t)
323322
324323 where req' = req { qParams = (T.pack pname, params') : qParams req }
325324 pname = symbolVal (Proxy :: Proxy sym)
326− params' = QueryPartParams $ (fmap . fmap) (toQueryParam)
325+ params' = QueryPartParams $ (fmap . fmap) toQueryParam
327326 paramlist
328327
329328
@@ -415,7 +414,7 @@ tattle = either Just (const Nothing)
415414-- > where host = BaseUrl Http "localhost" 8080
416415-- > -- then you can just use "addBook" to query that endpoint
417416
418−instance (MimeRender ct a, HasClient t m sublayout, Reflex t)
417+instance (Show a, ToJSON a, MimeRender ct a, HasClient t m sublayout, Reflex t)
419418 => HasClient t m (ReqBody (ct ': cts) a :> sublayout) where
420419
421420 type Client t m (ReqBody (ct ': cts) a :> sublayout) =
@@ -434,30 +433,26 @@ instance (MimeRender ct a, HasClient t m sublayout, Reflex t)
434433instance (KnownSymbol path, HasClient t m sublayout, Reflex t) => HasClient t m (path :> sublayout) where
435434 type Client t m (path :> sublayout) = Client t m sublayout
436435
437− clientWithRoute Proxy q req baseurl =
436+ clientWithRoute Proxy q req =
438437 clientWithRoute (Proxy :: Proxy sublayout) q
439438 (prependToPathParts (pure (Right $ T.pack p)) req)
440− baseurl
441439
442440 where p = symbolVal (Proxy :: Proxy path)
443441
444442instance HasClient t m api => HasClient t m (Vault :> api) where
445443 type Client t m (Vault :> api) = Client t m api
446444
447− clientWithRoute Proxy q req baseurl =
448− clientWithRoute (Proxy :: Proxy api) q req baseurl
445+ clientWithRoute Proxy = clientWithRoute (Proxy :: Proxy api)
449446
450447instance HasClient t m api => HasClient t m (RemoteHost :> api) where
451448 type Client t m (RemoteHost :> api) = Client t m api
452449
453− clientWithRoute Proxy q req baseurl =
454− clientWithRoute (Proxy :: Proxy api) q req baseurl
450+ clientWithRoute Proxy = clientWithRoute (Proxy :: Proxy api)
455451
456452instance HasClient t m api => HasClient t m (IsSecure :> api) where
457453 type Client t m (IsSecure :> api) = Client t m api
458454
459− clientWithRoute Proxy q req baseurl =
460− clientWithRoute (Proxy :: Proxy api) q req baseurl
455+ clientWithRoute Proxy = clientWithRoute (Proxy :: Proxy api)
461456
462457instance (HasClient t m api, Reflex t)
463458 => HasClient t m (BasicAuth realm usr :> api) where
testserver/Main.hs+17−9
@@ -5,24 +5,27 @@
55{-# LANGUAGE TypeFamilies #-}
66{-# LANGUAGE TypeOperators #-}
77
8+import Control.Monad.IO.Class (liftIO)
89import Data.Aeson
910import Data.Bool
10−import Data.Char (toUpper)
11−import qualified Data.List as L
11+import Data.Char (toUpper)
12+import qualified Data.List as L
1213import Data.Monoid
1314import Data.Proxy
14−import Data.Text hiding (length, null, map, head, toUpper)
15−import qualified Data.Text as T
15+import Data.Text hiding (head, length, map,
16+ null, toUpper)
17+import qualified Data.Text as T
18+import qualified Data.Text.IO as T
1619import GHC.Generics
17−import Snap.Http.Server
18−import Snap.Core
1920import Servant.Server.Internal.SnapShims
21+import Snap.Core
22+import Snap.Http.Server
2023
21−import Servant -- hiding (serveDirectory)
24+import Servant
2225import Servant.Server
2326-- import Snap.Util.FileServe
2427import API
25−import Snap
28+import Snap
2629
2730-- * Example
2831
@@ -45,7 +48,7 @@ data App = App
4548--
4649-- Each handler runs in the 'ExceptT ServantErr IO' monad.
4750server :: Server API (Handler App App)
48−server = return () :<|> return 100 :<|> sayhi :<|> dbl :<|> multi :<|> serveDirectory "static"
51+server = return () :<|> return 100 :<|> sayhi :<|> dbl :<|> multi :<|> qna :<|> serveDirectory "static"
4952 where sayhi :: Maybe Text -> [Text] -> Bool -> Handler App App Text
5053 sayhi nm greetings withGusto = case nm of
5154 Nothing -> return ("Sorry, who are you?" :: Text)
@@ -59,6 +62,11 @@ server = return () :<|> return 100 :<|> sayhi :<|> dbl :<|> multi :<|> serveDire
5962 return . modifier $ greetPart <> n
6063 dbl x = return $ x * 2
6164 multi = return . bool "Box unchecked" "Box Checked"
65+ qna q = do
66+ liftIO $ do
67+ putStrLn $ "qna got: " ++ show q
68+ T.putStrLn $ unQuestion q
69+ return $ Answer $ unQuestion q
6270
6371-- Turn the server into a WAI app. 'serve' is provided by servant,
6472-- more precisely by the Servant.Server module.
testserver/testserver.cabal+11−11
@@ -1,31 +1,31 @@
1−-- Initial back.cabal generated by cabal init. For further documentation,
1+-- Initial back.cabal generated by cabal init. For further documentation,
22-- see http://haskell.org/cabal/users-guide/
33
44name: testserver
55version: 0.1.0.0
6−-- synopsis:
7−-- description:
6+-- synopsis:
7+-- description:
88license: BSD3
99license-file: LICENSE
1010author: Greg Hale
1111maintainer: imalsogreg@gmail.com
12−-- copyright:
13−-- category:
12+-- copyright:
13+-- category:
1414build-type: Simple
15−-- extra-source-files:
15+-- extra-source-files:
1616cabal-version: >=1.10
1717
1818executable back
1919 main-is: Main.hs
20− -- other-modules:
21− -- other-extensions:
20+ -- other-modules:
21+ -- other-extensions:
2222 build-depends: aeson >= 0.9 && < 1.1
2323 , base >=4.8 && <4.10
2424 , snap >= 1.0 && < 1.1
2525 , snap-server >= 1.0 && < 1.1
2626 , snap-core >= 1.0 && < 1.1
27− , servant >= 0.7.1 && < 0.9
28− , servant-snap >= 0.7 && < 0.8
27+ , servant >= 0.10 && < 0.11
28+ , servant-snap >= 0.7.2 && < 0.8
2929 , text >= 1.2 && < 1.3
30− -- hs-source-dirs:
30+ -- hs-source-dirs:
3131 default-language: Haskell2010