1

我有来自 purescript-express 的以下代码(但问题更笼统)。

setHandler :: forall e. Handler e
setHandler = do
    idParam   <- getRouteParam "id"
    send "Yeah! "

appSetup :: forall e. App e
appSetup = do
    get "/set/:id" setHandler

setHandler需要具有get定义为的给定签名

> :t get
forall e r.
(RoutePattern r) => r
                    -> HandlerM ( express :: EXPRESS | e ) Unit
                    -> AppM ( express :: EXPRESS | e ) Unit

但是现在我想在其中使用以下功能setHandler

getPointsSet :: forall f. String -> Aff ( fs :: FS | f ) Foobar

这会给我以下编译器错误

[1/1 TypesDoNotUnify] src/Main.purs:31:5

          v
  31      send "Yeah! "
          ^

  Could not match type

    HandlerM

  with type

    Aff

  while trying to match type HandlerM
                               ( express :: EXPRESS
                               | _2
                               )
    with type Aff
                ( fs :: FS
                | _0
                )
  while checking that expression send "Yeah! "
    has type Aff
               ( fs :: FS
               | _0
               )
               _1
  in value declaration setHandler

我知道getPointsSet有效地使用需要 setHandler 也成为 a Aff,但我无法将它与getthen 连接起来。

编辑

如果我尝试按照liftAff以下答案中的建议添加

setHandler :: forall e. Handler e
setHandler = do
    idParam   <- getRouteParam "id"
    liftAff $ getPointsSet "../some-data.csv"
    send "Yeah! "

我收到以下错误

[1/1 NoInstanceFound] src/Main.purs:28:1
   28  setHandler :: forall e. Handler e
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   No type class instance was found for
   Control.Monad.Aff.Class.MonadAff ( fs :: FS | _0 )
                                 (HandlerM ( express :: EXPRESS | e0 ))

The instance head contains unknown type variables. Consider adding a type annotation.
in value declaration setHandler

我需要做什么来解决这个问题?

4

2 回答 2

5

似乎HandlerM有实例MonadAff,所以你可以使用liftAff. 像这儿:

setHandler :: forall e. Handler e
setHandler = do
  idParam   <- getRouteParam "id"
  liftAff $ getPointsSet "foo"
  send "Yeah! "

啊,对不起,行不统一没有额外的注释appSetupsetHandler

更新后的版本

appSetup :: forall e. App (fs :: FS|e)
appSetup =
  get "/set/:id" setHandler

setHandler :: forall e. Handler (fs :: FS|e)
setHandler = do
  idParam   <- getRouteParam "id"
  liftAff $ getPointsSet "../some-data.csv"
  send "Yeah! "

您还需要更改main类型

main :: forall e. Eff (express :: EXPRESS, fs :: FS|e) Unit
于 2016-03-21T20:10:05.160 回答
1

为了扩展Максим的答案,

setHandler的类型forall e. Handler e相当于HandlerM (express :: EXPRESS | e) Unit which 又相当于HandlerM (Request -> Response -> Eff (express :: EXPRESS | e) Unit -> Aff (express :: EXPRESS | e) Unit). 如果我们从构造函数中取出函数并为其提供参数(就像某些函数可能在幕后所做的那样),我们就剩下Aff (express :: EXPRESS | e) Unit)

getPointsSet的类型forall f. String -> Aff ( fs :: FS | f ) Foobar

所以基本上我们的问题可以归结为:类型(express :: EXPRESS | e)不与 统一( fs :: FS | f ),这意味着为了调用getPointsSetfrom setHandlersetHandler必须提供一个String(你提供"foo"的)和FS它当前不提供的效果。为了提供它, 的类型签名setHandler必须改变,所以Aff (express :: EXPRESS | e) Unit)我们不想拥有Aff (express :: EXPRESS, fs :: FS | r). 现在需要对main 不提供的效果main进行完全相同的分析setHandler。需要做出同样的改变。setHandlerFS

我希望这是有道理的。

于 2016-03-21T21:57:28.190 回答