我开始使用Netwire第5版。
编写我想将输入转换为输出的所有电线都没有问题。
现在是时候编写IO包装器以配合我的实际输入了,我有点困惑。
我是否应该为s
的{{1}}参数创建自定义会话类型并将传感器值嵌入其中?
如果是这样,我有这些问题:
Wire s e m a b
的{{1}}背景是什么?它用于什么?Monoid s
,但我的幺半群应该如何处理词典呢?它应该留下偏见吗?右侧偏置?以上都不是吗?如果没有,我该怎么办?对于某些class (Monoid s, Real t) => HasTime t s | s -> t
,我希望最终使用Map String Double
形式的电汇,代表我的输入。
我的理解是,我不想或不需要使用Wire s InhibitionReason Identity () Double
的{{1}}参数来实现此目的,允许电线本身纯净并限制IO到遍历顶层线路的代码。这是不正确的吗?
答案 0 :(得分:2)
将数据放入Wire s e m a b
的最简单方法是通过输入a
。通过使用WPure
或WGen
从状态增量s
或基础Monad
m
中获取数据是可能的,但这些可能会让我们更进一步远离主要的抽象。主要的抽象是Arrow
和Category
,它们只知道a b
,而不是s e m
。
这是一个非常简单的程序示例,提供输入作为输入a
。 double
是程序的最外层。 repl
是一个小的read-eval-print循环,调用stepWire
来运行电线。
import FRP.Netwire
import Control.Wire.Core
import Prelude hiding (id, (.))
double :: Arrow a => a [x] [x]
double = arr (\xs -> xs ++ xs)
repl :: Wire (Timed Int ()) e IO String String -> IO ()
repl w = do
a <- getLine
(eb, w') <- stepWire w (Timed 1 ()) (Right a)
putStrLn . either (const "Inhibited") id $ eb
repl w'
main = repl double
请注意,我们将时差传递给stepWire
,而不是总耗用时间。我们可以通过运行不同的顶级线来检查这是否正确。
timeString :: (HasTime t s, Show t, Monad m) => Wire s e m a String
timeString = arr show . time
main = repl timeString
具有所需的输出:
a
1
b
2
c
3
答案 1 :(得分:1)
我刚用Arrow方式解决了这个问题,所以这可能更具有可解性。如果你愿意,你可以阅读我的帖子。 Kleisli Arrow in Netwire 5?和Console interactivity in Netwire?。第二篇文章有一个完整的互动计划
首先,你需要这个来解除Kleisli函数(即任何a -> m b
):
mkKleisli :: (Monad m, Monoid e) => (a -> m b) -> Wire s e m a b
mkKleisli f = mkGen_ $ \a -> liftM Right $ f a
然后,假设您想从终端获取字符,可以通过这样做来提升hGetChar
:
inputWire :: Wire s () IO () Char
inputWire = mkKleisli $ \_ -> hGetChar stdin
我还没有测试过这个runWire
函数(我只是从以前的帖子中删除了代码),但它应该运行你的电汇:
runWire :: (Monad m) => Session m s -> Wire s e m () () -> m ()
runWire s w = do
(ds, s') <- stepSession s
-- | You don't really care about the () returned
(_, w') <- stepWire w ds (Right ())
runWire s' w'
您可以像任何其他电线或箭头一样在任何地方组合输入线。在我的例子中,我做了这个(不要复制,程序的其他部分是不同的):
mainWire = proc _ -> do
c <- inputWire -< ()
q <- quitWire -< c
outputWire -< c
returnA -< q
或者,单行:
mainWire = inputWire >>> (quitWire &&& outputWire) >>> arr (\(q,_) -> q)