2014-04-04 15 views
11

Tôi bắt đầu với Netwire phiên bản 5.Bắt đầu vào cho chương trình Netwire

Tôi không có vấn đề bằng văn bản tất cả các dây tôi muốn chuyển đổi đầu vào của tôi vào kết quả đầu ra của tôi.

Bây giờ đã đến lúc để viết wrapper IO để buộc ở đầu vào thực tế của tôi, và tôi là một chút bối rối.

Tôi có phải tạo loại phiên tùy chỉnh cho thông số s của Wire s e m a b và nhúng giá trị cảm biến vào đó không?

Nếu vậy, tôi có những câu hỏi này:

  1. chuyện gì với các Monoid s bối cảnh class (Monoid s, Real t) => HasTime t s | s -> t? Cái này được dùng để làm gì?
  2. Tôi đã nghĩ đến việc tacking trên Map String Double với cảm biến của tôi, nhưng làm thế nào monoid của tôi nên thắt chặt từ điển? Nó có nên thiên vị không? Phải thiên vị? Không có điều nào ở trên?

Nếu không, những gì tôi phải làm gì? Tôi muốn kết thúc bằng các dây có dạng Wire s InhibitionReason Identity() Double cho một số s, thể hiện ý kiến ​​của tôi. Đó là sự hiểu biết của tôi rằng tôi không muốn hoặc cần phải sử dụng thông số m monadic đơn lẻ của Wire cho mục đích này, cho phép các dây tự tinh khiết và giới hạn IO với mã đi qua dây cấp cao nhất (S). Điều này có đúng không?

+0

Có một trường hợp monoid cho Bản đồ những gì còn lại thiên vị. Và tôi thực sự nghĩ rằng làm cho bối cảnh đơn thuần ở đây một độc giả đọc và nhồi thông tin cảm biến của bạn trong đó sẽ là hợp lý ở đây. Điều này không thực sự ảnh hưởng đến nơi bạn bước dây của bạn bởi vì bạn có thể chỉ 'runReader' (hoặc' runReaderT' nếu bạn muốn công cụ trong nhiều thứ hơn). – Cubic

+0

Hướng dẫn/ví dụ ngoài đề xuất sử dụng các tác vụ IO trong dây bên trong để nhận dữ liệu cảm biến. ví dụ. sử dụng 'mkGen_' với' getKey' trong đó. Tôi sẽ quan tâm đến việc khái quát hóa câu hỏi: "Ưu điểm và nhược điểm của việc cho phép các hành động IO bên trong dây, so với việc cho ăn tất cả dữ liệu IO làm đầu vào cho dây ngoài cùng là gì?" – crosser

Trả lời

2

Cách đơn giản nhất để đưa dữ liệu vào một Wire s e m a b là thông qua các đầu vào a. Có thể, thông qua việc sử dụng WPure hoặc WGen để lấy dữ liệu ra khỏi vùng đồng bằng tiểu bang s hoặc bên dưới Monadm, nhưng chúng sẽ giúp chúng tôi tránh xa những trừu tượng chính. Các trừu tượng chính là ArrowCategory, mà chỉ biết về a b, và không phải là về s e m.

Dưới đây là một ví dụ về một chương trình rất đơn giản, cung cấp đầu vào như đầu vào a. double là dây ngoài cùng của chương trình. repl là một vòng lặp đọc nhỏ, có thể gọi là stepWire để chạy dây.

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 

Lưu ý rằng chúng tôi chuyển chênh lệch thời gian cho stepWire, không phải là tổng thời gian đã trôi qua. Chúng tôi có thể kiểm tra xem đây có phải là điều đúng đắn để thực hiện bằng cách chạy một dây cấp cao nhất khác không.

timeString :: (HasTime t s, Show t, Monad m) => Wire s e m a String 
timeString = arr show . time 

main = repl timeString 

Trong đó có các đầu ra mong muốn:

a 
1 
b 
2 
c 
3 
1

Tôi chỉ giải quyết điều này một cách mũi tên, vì vậy đây có thể là composible hơn. Bạn có thể đọc bài viết của tôi nếu bạn muốn. Kleisli Arrow in Netwire 5?Console interactivity in Netwire?.Các bài thứ hai có một chương trình tương tác hoàn chỉnh

Trước tiên, bạn cần điều này để nâng chức năng Kleisli (Tức là, bất cứ điều gì 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 

Sau đó, giả sử bạn muốn nhận được ký tự từ thiết bị đầu cuối, bạn có thể nâng hGetChar bằng cách làm này:

inputWire :: Wire s() IO() Char 
inputWire = mkKleisli $ \_ -> hGetChar stdin 

tôi đã không kiểm tra runWire chức năng này (tôi chỉ tước đang cất cánh từ bài viết trước đây của tôi), nhưng nó phải chạy dây của bạn:

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' 

Bạn có thể soạn dây đầu vào bất cứ nơi nào bạn muốn như bất kỳ Dây hoặc Mũi tên nào khác. Trong ví dụ của tôi, tôi đã làm điều này (không chỉ cần sao chép, các bộ phận khác của chương trình là khác nhau):

mainWire = proc _ -> do 
    c <- inputWire -<() 
    q <- quitWire -< c 
    outputWire -< c 
    returnA -< q 

Hoặc, một liner:

mainWire = inputWire >>> (quitWire &&& outputWire) >>> arr (\(q,_) -> q) 
Các vấn đề liên quan