如何统一这些类型?
How to unify these types?
我有以下来自 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 也变成 Aff
但是我不能用 get
连接它。
编辑
如果我尝试按照以下答案中的建议添加 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
我需要做什么来解决这个问题?
似乎HandlerM
有MonadAff
的实例,所以你可以使用liftAff
。喜欢这里:
setHandler :: forall e. Handler e
setHandler = do
idParam <- getRouteParam "id"
liftAff $ getPointsSet "foo"
send "Yeah! "
啊,抱歉,如果没有 appSetup
和 setHandler
的附加注释,行不会统一
更新版本
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
为了扩展 Максим 的回答,
您的 setHandler
的类型 forall e. Handler e
等同于 HandlerM (express :: EXPRESS | e) Unit
这又相当于 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 )
统一,这意味着为了从 setHandler
调用 getPointsSet
, setHandler
必须提供一个 String
(您提供 "foo"
)和它目前不提供的效果 FS
。为了提供它,setHandler
的类型签名必须改变,所以我们想要 Aff (express :: EXPRESS, fs :: FS | r)
而不是 Aff (express :: EXPRESS | e) Unit)
。现在还需要对 main
和 setHandler
进行完全相同的分析,setHandler
需要 main 不提供的效果 FS
。需要进行相同的更改。
我希望这是有道理的。
我有以下来自 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 也变成 Aff
但是我不能用 get
连接它。
编辑
如果我尝试按照以下答案中的建议添加 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
我需要做什么来解决这个问题?
似乎HandlerM
有MonadAff
的实例,所以你可以使用liftAff
。喜欢这里:
setHandler :: forall e. Handler e
setHandler = do
idParam <- getRouteParam "id"
liftAff $ getPointsSet "foo"
send "Yeah! "
啊,抱歉,如果没有 appSetup
和 setHandler
更新版本
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
为了扩展 Максим 的回答,
您的 setHandler
的类型 forall e. Handler e
等同于 HandlerM (express :: EXPRESS | e) Unit
这又相当于 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 )
统一,这意味着为了从 setHandler
调用 getPointsSet
, setHandler
必须提供一个 String
(您提供 "foo"
)和它目前不提供的效果 FS
。为了提供它,setHandler
的类型签名必须改变,所以我们想要 Aff (express :: EXPRESS, fs :: FS | r)
而不是 Aff (express :: EXPRESS | e) Unit)
。现在还需要对 main
和 setHandler
进行完全相同的分析,setHandler
需要 main 不提供的效果 FS
。需要进行相同的更改。
我希望这是有道理的。