首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Servant实现

Servant实现
EN

Stack Overflow用户
提问于 2017-08-28 02:28:06
回答 1查看 791关注 0票数 2

我想使用servant,特别是实现一个可读的haskell文件。我不知道如何使用haskell文件。我一直在搜索文档,但没有找到任何有用的东西。

到目前为止,我已经用扩展名.lhs正确地命名了文件,并且我已经执行了runhaskell filename.lhs。我收到以下错误:

代码语言:javascript
复制
servantfinaltest.lhs line 150: unlit: No definitions in file (perhaps you forgot the '>'s?)
`unlit' failed in phase `Literate pre-processor'. (Exit code: 1)

下面是我的.lhs文件:

代码语言:javascript
复制
# Serving an API

Enough chit-chat about type-level combinators and representing an API as a
type. Can we have a webservice already?

## A first example

Equipped with some basic knowledge about the way we represent APIs, let's now
write our first webservice.

The source for this tutorial section is a literate haskell file, so first we
need to have some language extensions and imports:

``` haskell

{-# LANGUAGE DataKinds #-}

{-# LANGUAGE DeriveGeneric #-}

{-# LANGUAGE FlexibleInstances #-}

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

{-# LANGUAGE MultiParamTypeClasses #-}

{-# LANGUAGE OverloadedStrings #-}

{-# LANGUAGE ScopedTypeVariables #-}

{-# LANGUAGE TypeOperators #-}

模块服务器,其中

导入前言()

导入Prelude.Compat

导入Control.Monad.Except

导入Control.Monad.Reader

导入Data.Aeson.Compat

导入Data.Aeson.Types

导入Data.Attoparsec.ByteString

导入Data.ByteString (ByteString)

导入Data.List

导入Data.Maybe

导入Data.String.Conversions

导入Data.Time.Calendar

导入GHC.Generics

导入Lucid

导入Network.HTTP.Media ((//),(/:))

导入Network.Wai

导入Network.Wai.Handler.Warp

导入佣人

导入System.Directory

导入Text.Blaze

导入Text.Blaze.Html.Renderer.Utf8

导入符合条件的Data.Aeson.Parser

导入符合条件的Text.Blaze.Html

代码语言:javascript
复制
**Important**: the `Servant` module comes from the **servant-server** package,
the one that lets us run webservers that implement a particular API type.  It
reexports all the types from the **servant** package that let you declare API
types as well as everything you need to turn your request handlers into a
fully-fledged webserver. This means that in your applications, you can just add
**servant-server** as a dependency, import `Servant` and not worry about anything
else.

We will write a server that will serve the following API.

``` haskell

type UserAPI1 = "users“:> Get 'JSON

代码语言:javascript
复制
Here's what we would like to see when making a GET request to `/users`.

``` javascript

[{“姓名”:“艾萨克·牛顿”,“年龄”:372,“电子邮件”:"isaac@newton.co.uk","registration_date":"1683-03-01"}

,{“姓名”:“阿尔伯特·爱因斯坦”,“年龄”:136,“电子邮件”:"ae@mc2.org","registration_date":"1905-12-01"}

]

代码语言:javascript
复制
Now let's define our `User` data type and write some instances for it.

``` haskell

数据用户=用户

{名称::字符串

,age ::Int

,email ::String

,registration_date ::Day

}派生(Eq,Show,Generic)

实例ToJSON用户

代码语言:javascript
复制
Nothing funny going on here. But we now can define our list of two users.

``` haskell

users1 ::用户

users1 =

[用户“艾萨克·牛顿”372 "isaac@newton.co.uk“(fromGregorian 1683 3 1)

,用户“艾伯特·爱因斯坦”136 "ae@mc2.org“(fromGregorian 1905 12 1)

]

代码语言:javascript
复制
Let's also write our API type.

``` haskell ignore

type UserAPI1 = "users“:> Get 'JSON

代码语言:javascript
复制
We can now take care of writing the actual webservice that will handle requests
to such an API. This one will be very simple, being reduced to just a single
endpoint. The type of the web application is determined by the API type,
through a *type family* named `Server`. (Type families are just functions that
take types as input and return types.)  The `Server` type family will compute
the right type that a bunch of request handlers should have just from the
corresponding API type.

The first thing to know about the `Server` type family is that behind the
scenes it will drive the routing, letting you focus only on the business
logic. The second thing to know is that for each endpoint, your handlers will
by default run in the `Handler` monad. This is overridable very
easily, as explained near the end of this guide. Third thing, the type of the
value returned in that monad must be the same as the second argument of the
HTTP method combinator used for the corresponding endpoint. In our case, it
means we must provide a handler of type `Handler [User]`. Well,
we have a monad, let's just `return` our list:

``` haskell

server1 ::服务器UserAPI1

server1 =返回users1

代码语言:javascript
复制
That's it. Now we can turn `server` into an actual webserver using
[wai](http://hackage.haskell.org/package/wai) and
[warp](http://hackage.haskell.org/package/warp):

``` haskell

userAPI ::Proxy UserAPI1

userAPI =代理

--“服务”来自于佣人,递给你一个WAI应用程序,

--你可以把它想象成一个“抽象的”网络应用程序,

--还不是网络服务器。

app1 ::应用程序

app1 = serve userAPI server1

代码语言:javascript
复制
The `userAPI` bit is, alas, boilerplate (we need it to guide type inference).
But that's about as much boilerplate as you get.

And we're done! Let's run our webservice on the port 8081.

``` haskell

main ::IO ()

main =运行8081 app1

代码语言:javascript
复制
EN

回答 1

Stack Overflow用户

发布于 2017-08-28 02:57:45

首先-如果你还没有写过任何haskell代码-从servant开始,我想说是相当雄心勃勃的-因为它利用了几个语言扩展提供的几个高级概念/机制,比如TypeFamiliesDataKinds……

您正在编写的是不识字的haskell文件-至少它违反了here所描述的语法

我建议要么坚持使用普通的haskell文件,要么先阅读我链接的文档。

以下是您的文件到有效的文字haskell的翻译:

代码语言:javascript
复制
# Serving an API

Enough chit-chat about type-level combinators and representing an API as a
type. Can we have a webservice already?

## A first example

Equipped with some basic knowledge about the way we represent APIs, let's now write our first webservice.

The source for this tutorial section is a literate haskell file, so first we need to have some language extensions and imports:

``` haskell

{-# LANGUAGE DataKinds #-}

{-# LANGUAGE DeriveGeneric #-}

{-# LANGUAGE FlexibleInstances #-}

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

{-# LANGUAGE MultiParamTypeClasses #-}

{-# LANGUAGE OverloadedStrings #-}

{-# LANGUAGE ScopedTypeVariables #-}

{-# LANGUAGE TypeOperators #-}

模块服务器,其中

导入前言()

导入Prelude.Compat

导入Control.Monad.Except

导入Control.Monad.Reader

导入Data.Aeson.Compat

导入Data.Aeson.Types

导入Data.Attoparsec.ByteString

导入Data.ByteString (ByteString)

导入Data.List

导入Data.Maybe

导入Data.String.Conversions

导入Data.Time.Calendar

导入GHC.Generics

导入Lucid

导入Network.HTTP.Media ((//),(/:))

导入Network.Wai

导入Network.Wai.Handler.Warp

导入佣人

导入System.Directory

导入Text.Blaze

导入Text.Blaze.Html.Renderer.Utf8

导入符合条件的Data.Aeson.Parser

导入合格的Text.Blaze.Html服务器重要提示:

代码语言:javascript
复制

模块来自servant- Servant包,该包允许我们运行实现特定Text.Blaze.Html类型的API服务器。它重新导出服务包中的所有类型,这些服务包允许您声明API类型以及将请求处理程序转换为功能齐全的let服务器所需的所有内容。这意味着在您的应用程序中,您只需添加servant-server作为依赖项,导入Servant,而不必担心else.We将编写的服务器将为以下

代码语言:javascript
复制
> type UserAPI1 = "users" :> Get '[JSON] [User]

提供服务。

,{“姓名”:“阿尔伯特·爱因斯坦”,“年龄”:136,“电子邮件”:"ae@mc2.org","registration_date":"1905-12-01"}

]

代码语言:javascript
复制
Now let's define our `User` data type and write some instances for it.

``` haskell

数据用户=用户

{名称::字符串

,age ::Int

,email ::String

,registration_date ::Day

}派生(Eq,Show,Generic)

实例ToJSON用户

代码语言:javascript
复制

这里没什么好笑的。但是现在我们可以定义两个用户的列表了。让我们同时编写

代码语言:javascript
复制
> users1 :: [User]
> users1 =
>   [ User "Isaac Newton"    372 "isaac@newton.co.uk" (fromGregorian 1683  3 1)
>   , User "Albert Einstein" 136 "ae@mc2.org"         (fromGregorian 1905 12 1)
>   ]

类型。

代码语言:javascript
复制
type UserAPI1 = "users" :> Get '[JSON] [User]

代码语言:javascript
复制
We can now take care of writing the actual webservice that will handle requests to such an API. This one will be very simple, being reduced to just a single endpoint. The type of the web application is determined by the API type, through a *type family* named `Server`. (Type families are just functions that take types as input and return types.)  The `Server` type family will compute the right type that a bunch of request handlers should have just from the
corresponding API type.

The first thing to know about the `Server` type family is that behind the
scenes it will drive the routing, letting you focus only on the business
logic. The second thing to know is that for each endpoint, your handlers will by default run in the `Handler` monad. This is overridable very
easily, as explained near the end of this guide. Third thing, the type of the value returned in that monad must be the same as the second argument of the HTTP method combinator used for the corresponding endpoint. In our case, it means we must provide a handler of type `Handler [User]`. Well,
we have a monad, let's just `return` our list:

``` haskell

server1 ::服务器UserAPI1

server1 =返回users1

代码语言:javascript
复制
That's it. Now we can turn `server` into an actual webserver using
[wai](http://hackage.haskell.org/package/wai) and
[warp](http://hackage.haskell.org/package/warp):

``` haskell

userAPI ::Proxy UserAPI1

userAPI =代理

代码语言:javascript
复制
'serve' comes from servant and hands you a WAI Application,
which you can think of as an "abstract" web application,
not yet a webserver.

```haskell

app1 ::应用程序

app1 = serve userAPI server1

代码语言:javascript
复制
The `userAPI` bit is, alas, boilerplate (we need it to guide type inference).
But that's about as much boilerplate as you get.

And we're done! Let's run our webservice on the port 8081.

```haskell

main ::IO ()

main =运行8081 app1

代码语言:javascript
复制
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45908060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档