序曲。我对Haskell和函数式编程一点也不熟悉,但我还是忍不住用Haskell编写代码,因为它太字典了!因此,我的问题可能非常简单和/或琐碎。我还在读“给你一个伟大的好的Haskell”,而且Monad还在路上。
考虑以下行为:
mousemove事件,当事件触发时,将它们推入堆栈
requestAnimationFrame启动循环
我无法意识到的是如何从事件中获得感兴趣的值,例如pageX或clientX,看起来我必须用数据定义来做一些事情,而且我被它困住了。请帮帮忙。
我也不知道如何检查外部函数的结果,例如,当我试图得到DOM元素时,结果可能是元素或null__,因此,比方说,getElById是不纯的,我需要检查我得到的结果。如何认识到这一点?似乎我可以用这样的东西:data Element = Null | Element ...然后模式匹配结果,但是如何使外部函数知道预期的结果呢?
更新
这里是理想逻辑的工作示例:
module MouseTracker where
import FFI
import Prelude
data Element
data Event
type EventStack = [Event]
data Frame
consLog :: a -> Fay ()
consLog = ffi "console.log(%1)"
reqFrame :: (Frame -> Fay ()) -> Fay ()
reqFrame = ffi "requestAnimationFrame(%1)"
getDoc :: Fay Element
getDoc = ffi "document"
createEl :: String -> Fay Element
createEl = ffi "document.createElement(%1)"
elById :: String -> Fay Element
elById = ffi "document.getElementById(%1)"
elSetId :: Element -> String -> Fay ()
elSetId = ffi "%1.setAttribute('id',%2)"
elSetHtml :: Element -> String -> Fay ()
elSetHtml = ffi "%1.innerHTML = %2"
docBodyAppend :: Element -> Fay ()
docBodyAppend = ffi "document.body.appendChild(%1)"
elListenWith :: Element -> String -> (Event -> Fay ()) -> Fay ()
elListenWith = ffi "%1.addEventListener(%2, %3)"
winListenWith :: String -> (Event -> Fay ()) -> Fay ()
winListenWith = ffi "window.addEventListener(%1,%2)"
docListener :: String -> (Event -> Fay ()) -> Fay ()
docListener evtType fn = do
doc <- getDoc
elListenWith doc evtType fn
createTrace :: Fay ()
createTrace = do
div <- createEl "div"
docBodyAppend div
elSetId div "trace"
createStack :: Fay ()
createStack = ffi "window._eventStack = []"
getStack :: Fay EventStack
getStack = ffi "window._eventStack"
updateStack :: EventStack -> Fay ()
updateStack = ffi "window._eventStack = %1"
emptyStack :: Fay ()
emptyStack = createStack
listenMice :: Fay()
listenMice = docListener "mousemove" trackMouse
where trackMouse :: Event -> Fay ()
trackMouse evt = do
stk <- getStack
updateStack (evt:stk)
renderFrame :: Frame -> Fay ()
renderFrame frame = do
stack <- getStack
if length stack > 0
then (do
let e = head stack
traceEventCoord e)
else (do return ())
reqFrame renderFrame
emptyStack
where traceEventCoord :: Event -> Fay ()
traceEventCoord e = do
eX <- pageX e
eY <- pageY e
let str = show eX ++ " x " ++ show eY
trace <- elById "trace"
elSetHtml trace str
pageX :: Event -> Fay Int
pageX = ffi "%1['pageX']"
pageY :: Event -> Fay Int
pageY = ffi "%1['pageY']"
main = do
docListener "DOMContentLoaded" $ \ _ -> do
putStrLn "DOM ready"
createTrace
createStack
listenMice
reqFrame renderFrame发布于 2013-12-30 00:15:13
有关声明数据类型及其权衡的不同方法,请参见这个答案。您是自己创建事件还是包装DOM事件?如果您正在包装,我建议您使用EmptyDataDecl。这意味着您没有针对每种事件的构造函数,但是您可以添加为您检查该类型的函数。如果您创建了自己的事件,那么在构造函数中使用正常的数据声明就更有意义了。
在包装DOM事件时,您将得到以下结果:
data Event
pageX :: Event -> Fay Int
pageX = ffi "%1['pageX']"Fay具有处理可空值的Nullable类型:
getElementById :: String -> Nullable Element
getElementById = ffi "document['getElementById'](%1)"这将在更详细的在维基上中描述。
https://stackoverflow.com/questions/20823763
复制相似问题