获取Netwire程序的输入

时间:2014-04-04 00:45:52

标签: haskell frp netwire

我开始使用Netwire第5版。

编写我想将输入转换为输出的所有电线都没有问题。

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

我是否应该为s的{​​{1}}参数创建自定义会话类型并将传感器值嵌入其中?

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

  1. Wire s e m a b的{​​{1}}背景是什么?它用于什么?
  2. 我正在考虑使用我的传感器读数来Monoid s,但我的幺半群应该如何处理词典呢?它应该留下偏见吗?右侧偏置?以上都不是吗?
  3. 如果没有,我该怎么办?对于某些class (Monoid s, Real t) => HasTime t s | s -> t,我希望最终使用Map String Double形式的电汇,代表我的输入。

    我的理解是,我不想或不需要使用Wire s InhibitionReason Identity () Double的{​​{1}}参数来实现此目的,允许电线本身纯净并限制IO到遍历顶层线路的代码。这是不正确的吗?

2 个答案:

答案 0 :(得分:2)

将数据放入Wire s e m a b的最简单方法是通过输入a。通过使用WPureWGen从状态增量s或基础Monad m中获取数据是可能的,但这些可能会让我们更进一步远离主要的抽象。主要的抽象是ArrowCategory,它们只知道a b,而不是s 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

答案 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)