2016-10-17 2 views
1

(지저분한, 아마 조리) Purescript 코드는 버튼을 누를하는 웹 소켓에 일부 텍스트 전송하는 장난감 테르밋/웹 소켓 스크립트 다음을 수행하십시오 RDOM.render 라인이 때가끔 {}의 ReactClass 소품을 갖는 것이 괜찮습니까?

module Main where 

import Prelude 
import React as R 
import React.DOM.Props as RP 
import ReactDOM as RDOM 
import Thermite as T 
import Control.Coroutine (cotransform, connect, runProcess, Producer, Consumer, consumer, producer, emit, ($$)) 
import Control.Coroutine.Aff (produce', produceAff, produce) 
import Control.Monad.Aff (launchAff, runAff, Aff) 
import Control.Monad.Aff.AVar (AVAR) 
import Control.Monad.Aff.Class (liftAff) 
import Control.Monad.Eff (Eff) 
import Control.Monad.Eff.Class (liftEff) 
import Control.Monad.Eff.Console (CONSOLE, log) 
import Control.Monad.Eff.Exception (EXCEPTION) 
import Control.Monad.Eff.Var (($=)) 
import Control.Monad.Writer (lift) 
import DOM (DOM) as DOM 
import DOM.HTML (window) as DOM 
import DOM.HTML.HTMLAnchorElement (download) 
import DOM.HTML.Types (htmlDocumentToParentNode) as DOM 
import DOM.HTML.Window (document) as DOM 
import DOM.Node.ParentNode (querySelector) as DOM 
import Data.Either (Either(..)) 
import Data.Generic (class Generic, gShow) 
import Data.Maybe (fromJust, Maybe(..)) 
import Data.Nullable (toMaybe) 
import Partial.Unsafe (unsafePartial) 
import React.DOM (text, p', td', input, tr', tbody', th, thead', table, div, h1', button) as R 
import Unsafe.Coerce (unsafeCoerce) 
import WebSocket (WEBSOCKET, Connection(..), Message(..), URL(..), runMessageEvent, runMessage, newWebSocket) 

data Action = SendButtonPress | SetText String 

derive instance genericAction :: Generic Action 

instance showAction :: Show Action where 
    show = gShow 

type State = { connection :: Connection 
      , someText :: String 
      } 

initialState :: Connection -> State 
initialState socket = { connection: socket 
         , someText: "" 
         } 

render :: T.Render State _ Action 
render dispatch _ state _ = 
    [ R.p' [ R.text "Value: " 
     , R.text $ show state.someText 
     ] 
    , R.p' [ R.input [ RP.placeholder "Enter rubbish here" 
        , RP.onChange \e -> dispatch (SetText (unsafeCoerce e).target.value) 
        ] [] 
     , R.button [ RP.onClick \_ -> dispatch SendButtonPress ] 
        [ R.text "Send"] 
     ] 
    ] 

performAction :: T.PerformAction _ State _ Action 
performAction SendButtonPress _ state  = void $ lift (sendMsg state.someText state.connection) 
performAction (SetText s) _ _ = void $ T.cotransform $ _ { someText = s} 

sendMsg :: forall a eff. (Show a) => a -> Connection -> Aff (ws :: WEBSOCKET, err :: EXCEPTION | eff) Unit 
sendMsg m (Connection s) = liftEff $ s.send (Message (show m)) 

spec :: T.Spec _ State _ Action 
spec = T.simpleSpec performAction render 

wsProducer :: forall eff. Connection -> Producer String (Aff (avar :: AVAR, err :: EXCEPTION, ws :: WEBSOCKET | eff)) Unit 
wsProducer (Connection s) = produce \emit -> do 
    s.onmessage $= \event -> do 
    emit $ Left $ runMessage (runMessageEvent event) 

wsConsumer :: forall t22 eff t31. (Show t31) => Consumer t31 (Aff (console :: CONSOLE | eff)) t22 
wsConsumer = consumer \msg -> do 
    liftEff $ log $ show msg 
    pure Nothing 

main :: Aff (avar :: AVAR, dom :: DOM.DOM, err :: EXCEPTION, ws :: WEBSOCKET, console :: CONSOLE) Unit 
main = do 
    socket <- liftEff $ newWebSocket (URL "ws://echo.websocket.org") [] 
    let state = initialState socket 
    component <- liftEff (gitItInTheDOM state) 
    runProcess (connect (wsProducer socket) (wsConsumer)) 

gitItInTheDOM :: forall eff props. State -> (Eff (dom :: DOM.DOM | eff) (R.ReactClass props)) 
gitItInTheDOM state = do 
    document <- DOM.window >>= DOM.document 
    let aJarOfSomeSort = DOM.querySelector "#container" (DOM.htmlDocumentToParentNode document) 
    container <- unsafePartial (fromJust <<< toMaybe <$> aJarOfSomeSort) 
    let component = T.createClass spec state 
    -- RDOM.render (R.createFactory component {}) container 
    pure component 

내 질문에 대한 gitItInTheDOM입니다 코드의 주석 처리를 해제하고 더 이상 유형을 확인하지 않습니다. , 어떻게 확인 입력 여전히 구성 요소를 반환 할 수 있습니다, 제발

gitItInTheDOM :: forall eff. State -> Eff (dom :: DOM.DOM | eff) Unit 
gitItInTheDOM state = void do 
    document <- DOM.window >>= DOM.document 
    let aJarOfSomeSort = DOM.querySelector "#container" (DOM.htmlDocumentToParentNode document) 
    container <- unsafePartial (fromJust <<< toMaybe <$> aJarOfSomeSort) 
    let component = T.createClass spec state 
    RDOM.render (R.createFactory component {}) container 

그러나 구성 요소를 반환하지 않습니다

Could not match type 

    {}                           

    with type                          

    props1                          


while trying to match type ReactClass {}                   
    with type ReactClass props1                     
while checking that expression (bind ((bind window) document)) (\$4 ->           
                    case $4 of          
                    document -> ...        
                   )             
    has type Eff                         
      (dom :: DOM                      
      | eff0                        
      )                         
      (ReactClass props1)                     
in value declaration gitItInTheDOM                    

where props1 is a rigid type variable                   
     bound at line 91, column 1 - line 97, column 8               
     eff0 is a rigid type variable                    
     bound at line 91, column 1 - line 97, column 8 

그러나 확인 입력 않습니다이에 gitItInTheDOM 변경 :이 오류 메시지가 무엇입니까? 특정 상황에서 유형 검사기가 props 매개 변수가 인 경우에만 createFactory을 수락하는 것으로 보입니다. 이러한 상황이 무엇인지, 그리고 유형 검사가 아닌 이유를 이해하지 못합니다.

성분을 puring의 아이디어는 가능하면 DOM 업데이트 할 수있어 그때 wsConsumer에 전달할 수 main에 '드라이버'를 전달한다 (사용하여 테르밋/반작용) 새로운 메시지는 웹 소켓을 통해 수신 될 때 . 이것이 의미가 없다면 이것이하려고하는 일을 성취 할 수있는 유효한 방법인지 전혀 모르겠습니다. 어떻게 유효하게 만들 수 있습니까? 당신이

gitItInTheDOM :: forall eff. State -> (Eff (dom :: DOM.DOM | eff) (R.ReactClass _))

에 원래 타입의 서명을 변경하는 경우

답변

2

이 유형 체킹이, 당신에게 와일드 카드에 대한 누락 유형을 알려 주어야합니다.

왜?

이것은 보편적 인 양화에 관한 것입니다. 원래 유형에는 forall props이 포함되어 있으므로 props을 인스턴스화하도록 선택한 모든 유형의 경우 gitItInTheDOM의 정의가 적합해야합니다. 실제로 T.createClass에서 반환 된 구성 요소는 props의 경우 에 대해 render 또는 performAction의 소품을 사용하지 않으므로 ReactClass props 유형을 제공 할 수 있으므로 명시 적으로 유도 된 유형 spec을 작성하여 확인할 수 있습니다 _에 대한 컴파일러의 불만에 의해. 당신이 당신의 구성 요소를 렌더링 행의 주석을 해제 할 때

은 그러나, R.createFactory는 함수가 props에 대한 어떤 유형의 작동 청구와 충돌, 특정 유형의 {}props 고정 값 {}와 함께 제공하고있다.

따라서 반환 유형 (... R.ReactClass {})을 수정하거나 발신자가 어떤 종류의 소품을 사용하도록 허용 할 수 있습니다.