Eco*_*ium 7 haskell haskell-wai servant
我正在按照本教程http://www.parsonsmatt.org/programming/2015/06/07/servant-persistent.html通过servant创建API.我想自定义服务器以提供静态文件,但无法找到方法.
我正在使用stack
构建工具.
我将Main.hs
文件的运行修改为include static
(run port $ static $ logger $ app cfg
)并导入Network.Wai.Middleware.Static (static)
.我还添加wai-middleware-static >=0.7.0 && < 0.71
到我的cabal文件中.
当我运行(更新:这部分完全是我的错误,我添加了封装到错误的小集团文件..跛脚导入Network.Wai.Middleware.Static作品和静态文件留在以下情况下,错误.任何人都搜索它并发现它很有用.)stack build
我得到:
Could not find module ‘Network.Wai.Middleware.Static’
Perhaps you meant
Network.Wai.Middleware.Gzip (from wai-extra-3.0.7.1@waiex_GpotceEdscHD6hq9p0wPOJ)
Network.Wai.Middleware.Jsonp (from wai-extra-3.0.7.1@waiex_GpotceEdscHD6hq9p0wPOJ)
Network.Wai.Middleware.Local (from wai-extra-3.0.7.1@waiex_GpotceEdscHD6hq9p0wPOJ)
Run Code Online (Sandbox Code Playgroud)
接下来我尝试使用servant serveDirectory
如下(简化):
type API = "users" :> Get '[JSON] [Person]
:<|> "static" :> Raw
server = createPerson :<|> serveDirectory "/static"
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
Couldn't match type ‘IO’ with ‘EitherT ServantErr IO’
arising from a functional dependency between:
constraint ‘Servant.Server.Internal.Enter.Enter
(IO Network.Wai.Internal.ResponseReceived)
(AppM :~> EitherT ServantErr IO)
(IO Network.Wai.Internal.ResponseReceived)’
arising from a use of ‘enter’
instance ‘Servant.Server.Internal.Enter.Enter
(m a) (m :~> n) (n a)’
at <no location info>
In the expression: enter (readerToEither cfg) server
In an equation for ‘readerServer’:
readerServer cfg = enter (readerToEither cfg) server
Run Code Online (Sandbox Code Playgroud)
我是Haskell初学者,我不熟悉围,所以不确定从哪里开始.我需要做什么更改才能在Blog帖子中制作示例代码来提供静态文件?
编辑:由于评论从默认视图隐藏,我在这里粘贴我的最后评论:
这是他博客中Matt 代码的低调版本.我将所有模块合并到一个文件中,删除了所有数据库内容,但没有清理扩展/导入.当我运行此代码时,我得到上面的类型不匹配错误.请注意,此代码不使用Network.Wai.Middleware.Static,我使用的是Servant StaticFiles的限定导入.
谢谢!
正如servant教程的相关部分所述,整个处理enter
是让你的请求处理程序使用一些monad m
(在你的情况下是一些ReaderT
monad)并提供一种方法将计算转换为servant标准monad中m
的计算.EitherT ServantErr IO
虽然这里的问题是,你定义在一堆请求处理程序ReaderT
和附加一个为静态文件,并呼吁enter
所有的这些.该ReaderT
处理器被转换为EitherT ...
处理得很好,但enter
尝试将转换serveDirectory
打来ReaderT ...
到EitherT ...
.这当然不会很快发生,因为开始时serveDirectory
不是计算ReaderT ...
!
仆人可以说是刚刚离开serveDirectory
独自-在这一点上我没有对我们是否应该这样做或不明确的意见,或者如果它是更好的只是有文件服务处理器分别粘,调用的结果enter
上所有其他端点.这是这样的样子(寻找-看新的变化):
type PersonAPI =
"users" :> Capture "name" String :> Get '[JSON] Person
-- NEW: removed Raw from here
-- NEW
type WholeAPI = PersonAPI :<|> Raw
type AppM = ReaderT Config (EitherT ServantErr IO)
userAPI :: Proxy PersonAPI
userAPI = Proxy
-- NEW
wholeAPI :: Proxy WholeAPI
wholeAPI = Proxy
-- NEW: changed 'userAPI' to 'wholeAPI'
app :: Config -> Application
app cfg = serve wholeAPI (readerServer cfg)
readerServer :: Config -> Server WholeAPI
readerServer cfg = enter (readerToEither cfg) server
:<|> S.serveDirectory "/static" -- NEW
readerToEither :: Config -> AppM :~> EitherT ServantErr IO
readerToEither cfg = Nat $ \x -> runReaderT x cfg
server :: ServerT PersonAPI AppM
server = singlePerson
singlePerson :: String -> AppM Person
singlePerson str = do
let person = Person { name = "Joe", email = "joe@example.com" }
return person
Run Code Online (Sandbox Code Playgroud)
无论如何,我已经把这个话题引起了其他仆人开发者的注意,谢谢!我们真的没有想过之间的相互作用enter
和serveDirectory
至今(当然,我没有).