- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在测试 Netwire
haskell 库并使其与一个简单的 time
一起工作金属丝:
import Control.Wire
import Prelude hiding ((.), id)
import Control.Monad.IO.Class
import Data.Functor.Identity
import System.IO
wire :: (HasTime t s) => Wire s () m a t
wire = time
run :: (HasTime t s, MonadIO m, Show b, Show e) =>
Session m s -> Wire s e m a b -> m ()
run session wire = do
(dt, session') <- stepSession session
(wt', wire') <- stepWire wire dt $ Right undefined
case wt' of
-- | Exit
Left _ -> return ()
Right x -> do
liftIO $ do
putChar '\r'
putStr $ either (\ex -> show ex) show wt'
hFlush stdout
-- Interactivity here?
gotInput <- hReady stdin
if gotInput then
return ()
else return ()
run session' wire'
main :: IO ()
-- main = testWire clockSession_ wire
main = run clockSession_ wire
run
基本修改自
testWire
,所以不知道是不是形成电线网络的正确方法。部分代码来源于
http://todayincode.tumblr.com/post/96914679355/almost-a-netwire-5-tutorial但该教程没有说明事件。
wire'
或改变行为。我试图阅读 API 文档和源代码,但我不知道如何实际“触发”事件或使用它来切换线路。
pollInput
进入另一个
IO
唯一的功能,耶!
import Control.Wire
import Prelude hiding ((.), id)
import Control.Monad.IO.Class
import Data.Functor.Identity
import System.IO
wire :: (HasTime t s) => Wire s () m a t
wire = time
run :: (HasTime t s, MonadIO m, Show b, Show e) =>
Session m s -> Wire s e m a b -> m ()
run session wire = do
-- Get input here
input <- liftIO $ pollInput
(dt, session') <- stepSession session
(wt', wire') <- stepWire wire dt $ input
case wt' of
-- | Exit
Left _ -> liftIO (putStrLn "") >> return ()
Right x -> do
liftIO $ do
putChar '\r'
putStr $ either (\ex -> show ex) show wt'
hFlush stdout
run session' wire'
pollInput :: IO (Either a b)
pollInput = do
gotInput <- hReady stdin
if gotInput then
return (Left undefined)
else return (Right undefined)
setup :: IO ()
setup = do
hSetBuffering stdin NoBuffering
hSetBuffering stdout NoBuffering
main :: IO ()
main = do
setup
run clockSession_ wire
pollInput
的类型是什么?我试图手动输入它但没有成功。不过,自动类型推导是有效的。
Left something
),并且会导致循环退出。当然,退出时,程序会产生一个换行符,让控制台看起来更好看。
Event
是如何工作的)
IORef
的单线程版本,也退出按 'x'Update 4:(但它不输出任何内容):
import Control.Wire
import Prelude hiding ((.),id)
import Control.Wire.Unsafe.Event
import System.IO
import Control.Monad.IO.Class
data InputEvent = KeyPressed Char
| NoKeyPressed
deriving (Ord, Eq, Read, Show)
type OutputEvent = IO ()
--- Wires
example :: (HasTime t s, Monad m, Show t) =>
Wire s () m (Event [InputEvent]) (Event [OutputEvent])
example = switch $
(fmap ((:[]) . print) <$> periodic 1 . time
&&&
fmap (const mkEmpty) <$> filterE (any (== KeyPressed 'x'))
)
readKeyboard :: IO (Either e (InputEvent))
readKeyboard = do
hSetBuffering stdin NoBuffering
gotInput <- hReady stdin
if gotInput then do
c <- getChar
return $ Right $ KeyPressed c
else return $ Right $ NoKeyPressed
output :: [OutputEvent] -> IO ()
output (x:xs) = id x >> output xs
output _ = return ()
run :: (HasTime t s, MonadIO m) =>
Session m s -> Wire s e m (Event [InputEvent]) (Event [OutputEvent]) -> m e
run = go
where
go session wire = do
-- | inputEvent :: Event InputEvent
inputEvent <- liftIO $ readKeyboard
(dt, session') <- stepSession session
(wt', wire') <- stepWire wire dt (Event <$> (fmap (:[]) inputEvent))
-- (wt', wire') <- stepWire wire dt (Right undefined)
case wt' of
Left a -> return a
Right bEvent -> do
case bEvent of
Event b -> liftIO $ output b
_ -> return ()
go session' wire'
main = do
run clockSession_ example
最佳答案
如果您不想阻塞输入和输出,请不要阻塞输入和输出。为了演示如何将 netwire 连接到事件,我们将制作一个运行线路的小框架。我们将通过执行所有 IO
来避免阻止电线的步进。在单独的线程中。
来自 netwire documentation ,我们可以解构 Event
如果我们正在开发一个框架。
Netwire does not export the constructors of the
Event
type by default. If you are a framework developer you can import theControl.Wire.Unsafe.Event
module to implement your own events.
Event
只是
data Event a = NoEvent | Event a
m
中的一个 Action 。一个用于输入,一个用于输出。它运行一个 Action
m (Either e a)
读取 Action 或禁止。它要么运行一个 Action
b -> m ()
线禁止时输出或停止。
import Control.Wire
import Prelude hiding ((.), id)
import Control.Wire.Unsafe.Event
run :: (HasTime t s, Monad m) =>
m (Either e a) -> (b -> m ()) ->
Session m s -> Wire s e m (Event a) (Event b) -> m e
run read write = go
where
go session wire = do
(dt, session') <- stepSession session
a <- read
(wt', wire') <- stepWire wire dt (Event <$> a)
case wt' of
Left e -> return e
Right bEvent -> do
case bEvent of
Event b -> write b
_ -> return ()
go session' wire'
'x'
时停止(禁止)。键被按下。
example :: (HasTime t s, Monad m, Show t) =>
Wire s () m (Event [InputEvent]) (Event [OutputEvent])
example = switch $
(fmap ((:[]) . print) <$> periodic 1 . time)
&&&
(fmap (const mkEmpty) <$> filterE (any (== KeyPressed 'x')))
IO
行动。
data InputEvent = KeyPressed Char
deriving (Ord, Eq, Read, Show)
type OutputEvent = IO ()
IORef
相互通信s。这对于示例程序(我们可以在阅读时只使用
hReady
)来说太过分了,对于生产程序来说还不够(IO 线程将旋转等待字符和输出)。在实践中,事件轮询和调度输出通常由其他一些 IO 框架(OpenGL、gui 工具包、游戏引擎等)提供。
import Data.IORef
type IOQueue a = IORef [a]
newIOQueue :: IO (IOQueue a)
newIOQueue = newIORef []
readIOQueue :: IOQueue a -> IO [a]
readIOQueue = flip atomicModifyIORef (\xs -> ([], reverse xs))
appendIOQueue :: IOQueue a -> [a] -> IO ()
appendIOQueue que new = atomicModifyIORef que (\xs -> (reverse new ++ xs, ()))
import Control.Concurrent.MVar
import Control.Concurrent.Async
import Control.Monad.IO.Class
runKeyboard :: (HasTime t s, MonadIO m) =>
Session m s -> Wire s e m (Event [InputEvent]) (Event [OutputEvent]) -> m e
runKeyboard session wire = do
stopped <- liftIO newEmptyMVar
let continue = isEmptyMVar stopped
inputEvents <- liftIO newIOQueue
outputEvents <- liftIO newIOQueue
inputThread <- liftIO $ async (readKeyboard continue (appendIOQueue inputEvents . (:[])))
outputThread <- liftIO $ async (runEvents continue (sequence_ <$> readIOQueue outputEvents))
let read = liftIO $ Right <$> readIOQueue inputEvents
let write = liftIO . appendIOQueue outputEvents
e <- run read write session wire
liftIO $ putMVar stopped ()
liftIO $ wait inputThread
liftIO $ wait outputThread
return e
KeyPressed
事件到队列。
import System.IO
readKeyboard :: IO Bool -> (InputEvent -> IO ()) -> IO ()
readKeyboard continue send = do
hSetBuffering stdin NoBuffering
while continue $ do
ifM (hReady stdin) $ do
a <- getChar
send (KeyPressed a)
ifM :: Monad m => m Bool -> m a -> m ()
ifM check act = do
continue <- check
if continue then act >> return () else return ()
while :: Monad m => m Bool -> m a -> m ()
while continue act = go
where
go = ifM continue loop
loop = act >> go
runEvents :: IO Bool -> (IO (IO ())) -> IO ()
runEvents continue fetch = (while continue $ fetch >>= id) >> fetch >>= id
runKeyboard
运行示例程序.
main = runKeyboard clockSession_ example
关于haskell - Netwire 中的控制台交互性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30992299/
我创建了一个包含 JavaScript 的 SVG 文件。 当我在 Chrome 中将此 SVG 文件作为独立文件运行时,它呈现正常。 当我将此 SVG 嵌入 HTML 页面时,它失去了交互性。 我做
我是 Qt 的新手,我发现学习它非常有益。我正在尝试将一些现有的 C++ 代码与新的 Qt GUI 合并。基本上,想法是让从 .avi 文件中提取的图像在后端进行处理,然后显示在屏幕上的 QLabel
下面的代码应该让矩形在按下键盘上的 WASD 键时移动。这不起作用。矩形不移动,但不会产生错误。我怎样才能做到这一点? 最佳答案 上面的代码不起作用,因为 x and y p
创建 map 后是否可以更改 map 是否具有交互性? 在 mapbox-gl-js 文档中,只能在创建 map 时将 map 标记为交互式或非交互式 (option.interactive)。但出于
我刚刚安装了 VS 2017 并正在打开一个在 VS 2015 中创建的 MVC 5 项目。该应用程序运行良好,但我的 MVC Razor View 代码和 2017 IDE 之间的交互性降低了。 这
我是一名优秀的程序员,十分优秀!