簡體   English   中英

在 PureScript 和 Halogen 中實現 websocket 重新連接的 EscapedSkolem 錯誤

[英]EscapedSkolem error implementing websocket reconnection in PureScript and Halogen

我正在嘗試在 PureScript 中實現 Websocket 重新連接,但完全不知道如何繼續。 由於使用了Aff ,我在頂層添加了重新連接代碼; 認為這是正確的地方,但我不確定。

我試圖像在 Haskell 中那樣實現它,但由於EscapedSkolem中的EscapedSkolem錯誤,我無法對其進行EscapedSkolem runWs 我的印象是我可以通過添加類型簽名來解決這個問題,但我一生都無法弄清楚簽名可能是什么!

所以我有三個問題:

  • 這是實現重新連接的正確方法嗎?
  • runWs的類型是runWs (關於我如何為自己解決這個問題的任何提示都會很棒)?
  • 如果添加類型簽名不能修復EscapedSkolem錯誤,我將如何修復它?

最后,當談到 PureScript 時,我是一個完全的新手,所以如果有任何不清楚的地方,請指出,我會盡力澄清。

編輯:添加了錯誤編譯器輸出並稍微更改了標題。

module Main where

import Prelude

import Control.Coroutine (Producer, Consumer, runProcess, consumer, ($$))
import Control.Coroutine.Aff (produce)

import Control.Monad.Aff (Aff, delay)
import Control.Monad.Aff.AVar (AVAR)
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (CONSOLE, log)
import Control.Monad.Eff.Exception (EXCEPTION)
import Control.Monad.Eff.Ref (REF)
import Control.Monad.Eff.Var (($=), get)

import DOM (DOM)
import DOM.Websocket.Event.CloseEvent (reason)


import Data.Either (Either(..))
import Data.Maybe (Maybe(..))
import Data.Time.Duration (Milliseconds(..))
import Halogen as H
import Halogen.Aff (HalogenEffects, awaitBody, runHalogenAff)
import Halogen.VDom.Driver (runUI)
import Log (Query(..), component)
import WebSocket (Connection(..), URL(..), WEBSOCKET, newWebSocket, runMessage, runURL, runMessageEvent)


wsURI :: URL
wsURI = URL "ws://localhost:6385"


reconnectionDelay :: Milliseconds
reconnectionDelay = Milliseconds 10000.0


main :: forall eff. Eff (HalogenEffects (console :: CONSOLE, err :: EXCEPTION , avar :: AVAR , dom :: DOM , exception :: EXCEPTION , ref :: REF , ws :: WEBSOCKET | eff)) Unit
main = do
  runHalogenAff do
    body <- awaitBody
    driver <- runUI component unit body

    ---> Replace this: <---
    runProcess (wsProducer $$ wsConsumer driver.query)
    ---> with this: <---
    --   runWs driver

-- -------------------------------------------------
-- -------------------------------------------------
--
-- Reconnection function
-- runWs :: ????????
runWs p = go
  where
    go = do
      runProcess (wsProducer $$ wsConsumer p)
      delay reconnectionDelay
      go

-- -------------------------------------------------
-- -------------------------------------------------


wsProducer :: forall eff. Producer String (Aff (console :: CONSOLE, err :: EXCEPTION , ws :: WEBSOCKET , avar :: AVAR | eff)) Unit
wsProducer = produce \emit -> do

  Connection socket <- newWebSocket wsURI []

  socket.onopen $= \event -> do
    log "onopen: Connection opened"
    log <<< runURL =<< get socket.url


  socket.onmessage $= \event -> do
    emit $ Left $ runMessage (runMessageEvent event)


  socket.onclose $= \event -> do
    log $ "Socket Closed, returning to runHalogenAff: "  <> reason event
    emit $ Right unit


  socket.onerror $= \event -> do
    log "Error."
    emit $ Right unit


wsConsumer :: forall eff . (Query ~> Aff (HalogenEffects eff)) -> Consumer String (Aff (HalogenEffects eff)) Unit
wsConsumer driver = consumer \msg -> do
  driver $ H.action $ AddMessage msg
  pure Nothing

編譯器輸出是:

Compiling Main
[1/1 MissingTypeDeclaration] src/Main.purs:54:1

      v
  54  runWs p = go
  55    where
  56      go = do
  57        runProcess (wsProducer $$ wsConsumer p)
  58        delay reconnectionDelay
  59        go
            ^

  No type declaration was provided for the top-level declaration of runWs.
  It is good practice to provide type declarations as a form of documentation.
  The inferred type of runWs was:

    forall t110 t120.
      (Query a0
      -> Aff
            ( avar :: AVAR
            , ref :: REF
            , exception :: EXCEPTION
            , dom :: DOM
            , console :: CONSOLE
            , err :: EXCEPTION
            , ws :: WEBSOCKET
            | t120
            )
            a0
      )
      -> Aff
          ( console :: CONSOLE
          , err :: EXCEPTION
          , ws :: WEBSOCKET
          , avar :: AVAR
          , dom :: DOM
          , exception :: EXCEPTION
          , ref :: REF
          | t120
          )
          t110

  where a0 is a rigid type variable
          bound at line 57, column 44 - line 57, column 45

[1/1 EscapedSkolem] src/Main.purs:54:1

      v
  54  runWs p = go
  55    where
  56      go = do
  57        runProcess (wsProducer $$ wsConsumer p)
  58        delay reconnectionDelay
  59        go
            ^

  The type variable a, bound at

    /home/rgh/dev/purescript/translate/sidebar/src/Main.purs line 57, column 44 - line 57, column 45

  has escaped its scope, appearing in the type

    (Query a2
    -> Aff
          ( avar :: AVAR
          , ref :: REF
          , exception :: EXCEPTION
          , dom :: DOM
          , console :: CONSOLE
          , err :: EXCEPTION
          , ws :: WEBSOCKET
          | t120
          )
          a2
    )
    -> Aff
        ( console :: CONSOLE
        , err :: EXCEPTION
        , ws :: WEBSOCKET
        , avar :: AVAR
        , dom :: DOM
        , exception :: EXCEPTION
        , ref :: REF
        | t120
        )
        t110

  in the expression \p ->
                      let
                        go = ...
                      in go
  in value declaration runWs

          Src   Lib   All
Warnings   1     0     1
Errors     1     0     1
* Failed to rebuild; try to fix the compile errors

編譯器錯誤消息有時可能難以解密,但在這種情況下,它就是您正在尋找的答案。 讓我們在這里看看你的 do 塊:

do
  runHalogenAff do
    body <- awaitBody
    driver <- runUI component unit body
    runWs driver.query -- < assuming you made a small mistake here

我通常從脫糖開始,我發現它更容易遵循類型,但是 ymmv:

runHalogenAff $
  awaitBody >>= \body ->
    runUI component unit body >>= \driver ->
      runWs driver.query

查看runHalogenAff的簽名,我們可以看到它接受類型為Aff (HalogenEffects eff) x ,這意味着以下術語必須評估為該類型的值。 然后runWs必須返回該類型的值。

現在讓我們轉向runWs 它的參數是一個自然變換f ~> m在你的例子中它把你的查詢代數帶入Aff monad 我們可以把它寫下來,讓編譯器為我們解決剩下的問題:

runWs :: (Query ~> Aff _) -> Aff _ Unit

這將成功構建並為您提供可以填補這些漏洞的東西。 這是最終的簽名:

runWs :: forall eff. 
      (Query ~> Aff (HalogenEffects 
        ( console :: CONSOLE
        , err :: EXCEPTION
        , ws :: WEBSOCKET
        | eff
        )))
      -> Aff (HalogenEffects
        ( console :: CONSOLE
        , err :: EXCEPTION
        , ws :: WEBSOCKET
        | eff
        )) Unit

事實上,這正是編譯器輸出給你的。 我假設錯誤消息“類型變量 a 已超出其范圍”是因為自然變換定義中的全稱量詞。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM