2014-04-04 40 views
11

我开始使用Netwire版本5获取输入Netwire程序

我没有问题,写我所想我的投入转化为产出我的电线。

现在时间已经到了写IO包装在我的现实世界的输入领带,我有点糊涂了。

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

如果是这样,我有以下问题:

  1. 这是怎么回事用class (Monoid s, Real t) => HasTime t s | s -> tMonoid s背景?它是干什么用的?
  2. 我想会附上我的传感器读数Map String Double的,但我的幺应该如何紧缩的词典?它应该是左偏吗?右侧偏置?以上都不是?

如果不是,那我该怎么办?我想以Wire s InhibitionReason Identity() Double的形式结束一些s,代表我的意见。

这是我的理解,我不想要或需要使用Wire的单子m参数用于此目的,使线本身是纯粹的和围在IO于通过顶层线步骤的代码( S)。这是不正确的?

+0

有用于地图幺半群实例剩下的失之偏颇。而且我实际上认为在这里将monadic语境设置为读者monad,并将感应器信息填充到这里是合理的。这并不会真正影响你接线的地方,因为你可以'runReader'(或者'runReaderT',如果你想要更多东西的话)。 – Cubic

+0

教程/示例提示在内部线路中使用IO操作来获取传感器数据。例如在'getKey'中使用'mkGen_'。我有兴趣将问题概括为:“与将所有IO数据作为输入馈送到最外层导线相比,允许在导线内部进行IO操作的优点和缺点是什么?” – crosser

回答

2

将数据放入一个Wire s e m a b的最简单方法是通过输入a。有可能通过使用WPureWGen从状态delta s或基础Monadm中获取数据,但这些使我们远离主要抽象。主要的抽象是ArrowCategory,只知道a b,而不是s e m

这里的一个非常简单的程序的一个例子,提供作为输入adouble是程序的最外层线。 repl是一个小型的读取 - 评估打印循环,调用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

我只是在箭头的方式解决了这个,所以这可能是更composible。你可以阅读我的帖子,如果你喜欢。 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)