如何以 NCurses getEvent 为条件

How to do conditional on NCurses getEvent

我正在查看这里的信息:Hackage

我希望在我的程序中根据按下的箭头键发生不同的事情。使用 NCurses 模块,我可以使用 getEvent 函数注册一个事件。但是我无法让我的 if 语句处理存储的事件。这是我的代码:

main = runCurses $ do
    w <- defaultWindow
    e <- getEvent w (Just 300)
    let x = setX e

setX e
    | e == KeyLeftArrow = -1
    | e == KeyRightArrow = 1
    | otherwise = 0

这给出Couldn't match expected type ‘Key’ with actual type ‘Maybe Event’所以我改成e == Just Key...Arrow然后得到

Couldn't match type ‘Event’ with ‘Key’
      Expected type: Maybe Key
        Actual type: Maybe Event

我想这是因为 e 是一个事件,我表现得好像它是一个密钥,但即使尝试了这个 Key e == Just Key...Arrow 它也没有用。我怎样才能把这个事件变成一个关键?或者以其他方式让我的 e 条件生效?

查看getEvent定义

getEvent
  :: Window  
  -> Maybe Integer  
  -> Curses (Maybe Event)

您可能会注意到它 returns Maybe Event 包装到 Curses monad 中。在 setX 函数中,您试图将事件与键进行比较。 编译器准确地告诉您这种不匹配:

Couldn't match type ‘Event’ with ‘Key’
  Expected type: Maybe Key
    Actual type: Maybe Event

让我们转到文档并查找有关 EventKey 类型的更多信息。 Event 的定义如下:

data Event
    = EventCharacter Char
    | EventSpecialKey Key
    | EventMouse Integer MouseState
    | EventResized
    | EventUnknown Integer

您可能会注意到 Event 有几个变体(构造函数),其中之一 EventSpecialKey 包装 Key。这正是您所需要的。

setX e
    | e == Just (EventSpecialKey KeyLeftArrow) = -1
    | e == Just (EventSpecialKey KeyRightArrow) = 1
    | otherwise = 0

您已正确识别问题。你提出的解决方案,将 Key 放在等号的左侧,是 断言 你有一把钥匙,当你已经确定你实际上没有吨!

查看包 link 发现 Event 可能是按键 EventSpecialKey Key。因此,

setX e = case e of --lambdacase would be even more idiomatic
    Just (EventSpecialKey KeyLeftArrow) -> -1
    Just (EventSpecialKey KeyRightArrow) -> 1
    _ -> 0