Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Send as monad #55

Merged
merged 2 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions docs/src/00-foreword.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ The main features are:

* easy to use. It has simple design on purpose

* it defines no custom server monads. I promise you

* expressive DSL to compose servers

* type-safe route handlers and conversions
Expand Down Expand Up @@ -40,7 +38,7 @@ server = "api/v1/hello" /. hello

-- | The handler definition as a function
hello :: Get (Resp Text)
hello = Send $ pure $ ok "Hello World"
hello = pure $ ok "Hello World"
```


Expand Down
8 changes: 5 additions & 3 deletions docs/src/01-hello-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ We have type synonyms for all HTTP-methods (`Get`, `Post`, `Put` etc).

It's interesting to know that library mig does not use any custom monads for operation.
Instead it runs on top of monad provided by the user. Usually it would be `IO` or `Reader` over `IO`.
Also for convenience `Send` is also `Monad`, `MonadTrans` and `MonadIO`.
So we can omit `Send` constructor in many cases.

### HTTP-response type

Expand Down Expand Up @@ -143,7 +145,7 @@ Let's complete the example and define a handler which returns static text:

```haskell
hello :: Get IO (Resp Json)
hello = Send $ pure $ ok "Hello World!"
hello = pure $ ok "Hello World!"
```

We have several wrappers here:
Expand Down Expand Up @@ -193,7 +195,7 @@ server :: Server IO
server = "api/v1/hello" /. hello

hello :: Get IO (Resp Json Text)
hello = Send $ pure $ ok "Hello World!"
hello = pure $ ok "Hello World!"
```

If we run the code we can test it with `curl` in command line:
Expand All @@ -210,7 +212,7 @@ Let's define another handler to say `bye`:

```haskell
bye :: Get IO (Resp Json)
bye = Send $ pure $ ok "Goodbye"
bye = pure $ ok "Goodbye"
```

We can add it to the server with monoid method as `Server m` is a `Monoid`:
Expand Down
26 changes: 13 additions & 13 deletions docs/src/02-request-anatomy.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ by the name:

```haskell
hello :: Query "who" Text -> Get (Resp Text)
hello (Query name) = Send $
hello (Query name) =
pure $ ok $ "Hello " <> name
```

Expand Down Expand Up @@ -109,7 +109,7 @@ queries in the handler. For example if we want to greet two persons we can write

```haskell
hello :: Query "personA" Text -> Query "personB" Text -> Get (Resp Text)
hello (Query nameA) (Query nameB) = Send $
hello (Query nameA) (Query nameB) =
pure $ ok $ "Hello " <> nameA <> " and " <> nameB
```

Expand All @@ -118,7 +118,7 @@ For example let's add two numbers:

```haskell
add :: Query "a" Int -> Query "b" Int -> Get (Resp Int)
add (Query a) (Query b) = Send $
add (Query a) (Query b) =
pure $ ok (a + b)
```

Expand All @@ -131,7 +131,7 @@ Let's for example query numbers for addition as capture parameters:

```haskell
add :: Capture "a" Int -> Capture "b" Int -> Get (Resp Int)
add (Query a) (Query b) = Send $
add (Query a) (Query b) =
pure $ ok (a + b)
```

Expand Down Expand Up @@ -176,7 +176,7 @@ For the example we haven't altered the server and our example:

```haskell
add :: Query "a" Int -> Query "b" Int -> Get (Resp Int)
add (Query a) (Query b) = Send $
add (Query a) (Query b) =
pure $ ok (a + b)

server = "api/v1/add" /. add
Expand Down Expand Up @@ -223,7 +223,7 @@ data AddInput = AddInput

-- | Using JSON as body request
handleAddJson :: Body AddInput -> Post (Resp Int)
handleAddJson (Body (AddInput a b)) = Send $
handleAddJson (Body (AddInput a b)) =
pure $ ok $ a + b
```

Expand Down Expand Up @@ -291,7 +291,7 @@ server =

-- | Simple getter
helloWorld :: Get (Resp Text)
helloWorld = Send $ do
helloWorld = do
pure $ ok "Hello world!"

newtype TraceId = TraceId Text
Expand All @@ -301,25 +301,25 @@ newtype TraceId = TraceId Text
and using conditional output status
-}
handleSucc :: Header "Trace-Id" TraceId -> Query "value" Int -> Get (Resp Int)
handleSucc (Header _traceId) (Query n) = Send $ do
handleSucc (Header _traceId) (Query n) =
pure $ ok (succ n)

-- | Using optional query parameters.
handleSuccOpt :: Optional "value" Int -> Get (Resp Int)
handleSuccOpt (Optional n) = Send $ do
handleSuccOpt (Optional n) =
pure $ case n of
Just val -> ok (succ val)
Nothing -> ok 0

{-| Using several query parameters
-}
handleAdd :: Query "a" Int -> Query "b" Int -> Get (Resp Int)
handleAdd (Query a) (Query b) = Send $ do
handleAdd (Query a) (Query b) =
pure $ ok $ a + b

-- | Using query flag if flag is false returns 0
handleAddIf :: Query "a" Int -> Query "b" Int -> QueryFlag "perform" -> Get (Resp Int)
handleAddIf (Query a) (Query b) (QueryFlag addFlag) = Send $ do
handleAddIf (Query a) (Query b) (QueryFlag addFlag) = do
pure $
ok $
if addFlag
Expand All @@ -332,7 +332,7 @@ captured in URL. For example:
> http://localhost:8085/hello/api/mul/3/100
-}
handleMul :: Capture "a" Int -> Capture "b" Int -> Get (Resp Int)
handleMul (Capture a) (Capture b) = Send $ do
handleMul (Capture a) (Capture b) = do
pure $ ok (a * b)

data AddInput = AddInput
Expand All @@ -343,7 +343,7 @@ data AddInput = AddInput

-- | Using JSON as input
handleAddJson :: Body AddInput -> Post (Resp Int)
handleAddJson (Body (AddInput a b)) = Send $ do
handleAddJson (Body (AddInput a b)) =
pure $ ok $ a + b
```

Expand Down
4 changes: 2 additions & 2 deletions docs/src/03-response-anatomy.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ server =
"square-root" /. squareRoot

squareRoot :: Body Float -> Post (RespOr Text Float)
squareRoot (Body arg) = Send $ pure $
squareRoot (Body arg) = pure $
if arg >= 0
then ok (sqrt arg)
else bad badRequest400 "Argument for square root should be non-negative"
Expand All @@ -161,7 +161,7 @@ trace id from request to the response. Let's do it with `addHeaders`:

```haskell
passTrace :: Header "trace-id" Text -> Post (Resp ())
passTrace (Header traceId) = Send $
passTrace (Header traceId) =
pure $ addHeaders [("trace-id", toHeader traceId)] $ ok ()
```

Expand Down
2 changes: 1 addition & 1 deletion examples/mig-example-apps/HelloWorld/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ server = "api/v1/hello" /. hello

-- | Handler takes no inputs and marked as Get HTTP-request that returns Text response as Json.
hello :: Get IO (Resp Json Text)
hello = Send $ pure $ ok "Hello World!"
hello = pure $ ok "Hello World!"
23 changes: 11 additions & 12 deletions examples/mig-example-apps/RouteArgs/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ routeArgs =

-- | Simple getter
helloWorld :: Get (Resp Text)
helloWorld = Send $ do
helloWorld = do
pure $ ok "Hello world!"

newtype TraceId = TraceId Text
Expand All @@ -56,7 +56,7 @@ newtype TraceId = TraceId Text
and using conditional output status
-}
handleSucc :: Header "Trace-Id" TraceId -> Query "value" Int -> Get (Resp Int)
handleSucc (Header traceId) (Query n) = Send $ do
handleSucc (Header traceId) (Query n) = do
pure $ setHeader "Trace-Id" traceId $ setStatus st $ ok (succ n)
where
st
Expand All @@ -65,7 +65,7 @@ handleSucc (Header traceId) (Query n) = Send $ do

-- | Using optional query parameters and error as RespOr.
handleSuccOpt :: Optional "value" Int -> Get (RespOr Text Int)
handleSuccOpt (Optional n) = Send $ do
handleSuccOpt (Optional n) = do
pure $ case n of
Just val -> ok (succ val)
Nothing -> bad status500 "error: no input"
Expand All @@ -75,14 +75,14 @@ Note that function can have any number of arguments.
We encode the input type with proper type-wrapper.
-}
handleAdd :: Query "a" Int -> Query "b" Int -> Get (Resp Int)
handleAdd (Query a) (Query b) = Send $ do
handleAdd (Query a) (Query b) = do
pure $ addHeaders headers $ ok $ a + b
where
headers = [("args", "a, b")]

-- | Using query flag if flag is false returns 0
handleAddIf :: Query "a" Int -> Query "b" Int -> QueryFlag "perform" -> Get (Resp Int)
handleAddIf (Query a) (Query b) (QueryFlag addFlag) = Send $ do
handleAddIf (Query a) (Query b) (QueryFlag addFlag) = do
pure $
ok $
if addFlag
Expand All @@ -95,7 +95,7 @@ captured in URL. For example:
> http://localhost:8085/hello/api/mul/3/100
-}
handleMul :: Capture "a" Int -> Capture "b" Int -> Get (Resp Int)
handleMul (Capture a) (Capture b) = Send $ do
handleMul (Capture a) (Capture b) = do
pure $ ok (a * b)

data AddInput = AddInput
Expand All @@ -106,13 +106,12 @@ data AddInput = AddInput

-- | Using JSON as input
handleAddJson :: Body AddInput -> Post (Resp Int)
handleAddJson (Body (AddInput a b)) = Send $ do
handleAddJson (Body (AddInput a b)) = do
pure $ ok $ a + b

handleSquareRoot :: Body Float -> Post (RespOr Text Float)
handleSquareRoot (Body arg) =
Send $
pure $
if arg >= 0
then ok (sqrt arg)
else bad badRequest400 "Argument for square root should be non-negative"
pure $
if arg >= 0
then ok (sqrt arg)
else bad badRequest400 "Argument for square root should be non-negative"
Loading