11

我开始使用 Netwire 版本 5。

我可以毫无问题地编写我想将输入转换为输出的所有线路。

现在是时候编写 IO 包装器来绑定我的实际输入了,我有点困惑。

我是否应该为s参数创建一个自定义会话类型Wire s e m a b并将我的传感器值嵌入其中?

如果是这样,我有这些问题:

  1. Monoid s上下文是class (Monoid s, Real t) => HasTime t s | s -> t怎么回事?它是干什么用的?
  2. 我正在考虑Map String Double用我的传感器读数添加一个,但是我的幺半群应该如何处理字典呢?应该偏左吗?偏右?以上都不是?

如果没有,我该怎么办?Wire s InhibitionReason Identity () Double我想以some形式的线结束s,代表我的输入。

我的理解是,我不想或不需要为此目的使用 monadicm参数Wire,允许线路本身是纯的,并将 IO 限制在通过顶层线路的代码中。这是不正确的吗?

4

2 回答 2

2

将数据放入 a 的最简单方法Wire s e m a b是通过 input a。有可能通过使用WPure或从状态 delta或底层WGen中获取数据,但这些使我们远离主要抽象。主要的抽象是and ,它只知道 about ,而不知道 about 。sMonad mArrowCategorya bs e m

这是一个非常简单的程序示例,提供输入作为输入adouble是程序的最外层线。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
于 2014-09-03T04:16:20.830 回答
1

我只是以箭头方式解决了这个问题,所以这可能更可组合。喜欢的可以看我的帖子。Netwire 5中的Kleisli Arrow?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)
于 2015-09-29T22:22:01.783 回答