简体   繁体   中英

Purescript cannot get keycode from keyboard

I am new to functional programming and to Purescript. I am trying to get keycode from keys pressed from keyboard. I have made a eventListener which fires when keydown event is fired and triggers event listener function test. I am having problem in converting event to keyboardevent and getting keycode from keyboardevent. I am attaching my code and error it producing.

import Control.Monad.Eff (Eff)
    import Control.Monad.Eff.Class
    import Control.Monad.Eff.Console (CONSOLE, log)
    import DOM (DOM)
    import DOM.Event.EventTarget (addEventListener, eventListener)
    import DOM.HTML.Types as DHT
    import DOM.Event.KeyboardEvent as KE
    import DOM.Event.Types (EventType(..), EventTarget)
    import DOM.Event.Event
    import DOM.HTML (window)
    import DOM.HTML.Window (document)
    import Prelude (Unit)

test :: forall e. Event -> Eff ( console :: CONSOLE, dom :: DOM | e) Unit
    test a = do
      ke <-  KE.eventToKeyboardEvent a
      co <-  KE.key ke
      log "Key Pressed : "

    main :: forall e. Eff (console :: CONSOLE, dom :: DOM | e) Unit
    main = do
      documenttarget <- liftEff $ window >>= document <#> DHT.htmlDocumentToEventTarget
      addEventListener (EventType "keydown") (eventListener test) true (documenttarget)

Error :

Error found:
in module Main
at src/Main.purs line 30, column 10 - line 30, column 19

  Could not match type

    String

  with type

    t0 t1


while checking that type String
  is at least as general as type t0 t1
while checking that expression key ke
  has type t0 t1
in value declaration test

where t0 is an unknown type
      t1 is an unknown type

See https://github.com/purescript/documentation/blob/master/errors/TypesDoNotUnify.md for more information,
or to contribute content related to this error.


* ERROR: Subcommand terminated with exit code 1

Your test function needs tweaking a bit:

import Prelude

import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Class (liftEff)
import Control.Monad.Eff.Console (CONSOLE, log)
import Control.Monad.Except (runExcept)
import DOM (DOM)
import DOM.Event.Event (Event)
import DOM.Event.EventTarget (addEventListener, eventListener)
import DOM.Event.KeyboardEvent as KE
import DOM.Event.Types (EventType(..))
import DOM.HTML (window)
import DOM.HTML.Types as DHT
import DOM.HTML.Window (document)
import Data.Either (Either(..))

test :: forall e. Event -> Eff ( console :: CONSOLE, dom :: DOM | e) Unit
test a =
  case runExcept (KE.eventToKeyboardEvent a) of
    Left err ->
      log "Event was not a keyboard event"
    Right ke -> do
      let co = KE.key ke
      log "Key Pressed : "

main :: forall e. Eff (console :: CONSOLE, dom :: DOM | e) Unit
main = do
  documenttarget <- liftEff $ window >>= document <#> DHT.htmlDocumentToEventTarget
  addEventListener (EventType "keydown") (eventListener test) true (documenttarget)

First, KE.key and KE.eventToKeyboardEvent are not effectful functions, which means you don't need to bind to get the values from them (this is what the t0 t1 error was about: it expects the resulting value to be like m String rather than just String , for some m ).

Next, when we use eventToKeyboardEvent , it can fail, since we have no way of guaranteeing that it's safe to coerce any Event to a KeyboardEvent . The result is wrapped in F , which is a synonym for Except MultipleErrors , so we need to do something to get the result of that. We "run" the Except wrapper that gives us an Either back, where the Left side is the error message and Right is the success result.

In this example I made it log when the cast fails, but you probably don't care about that, and generally don't even expect that case to be hit, in which case using pure unit is probably good enough instead.

There's actually another way of writing this if you're happy to let the failure case do nothing:

import Data.Foldable (for_)

test :: forall e. Event -> Eff ( console :: CONSOLE, dom :: DOM | e) Unit
test a =
  for_ (runExcept (KE.eventToKeyboardEvent a)) \ke -> do
    let co = KE.key ke
    log "Key Pressed : "

for_ is actually a highly generic function that can be used for a variety of stuff, but this usage of it to absorb failures silently is pretty handy when writing code against the ugly DOM API.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM