2014-04-04 45 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)