Получение информации о программах Netwire

Я начинаю с Netwire версии 5.

У меня нет проблем с записью всех проводов, которые я хочу преобразовать в мои входы.

Теперь пришло время написать оболочку ввода-вывода, чтобы связать ее с реальными данными, и я немного запутался.

Я должен создать пользовательский тип сеанса для 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 для некоторых s, представляющий мой вклад.

Это мое понимание, что я не хочу или не нужно использовать монадический m параметр Wire для этого, позволяя самим проводам быть чистыми и ограничивая ввод-вывод кодом, который проходит по проводам верхнего уровня. Это неверно?

2 ответа

Самый простой способ поместить данные в Wire s e m a b через вход a, Это возможно благодаря использованию WPure или же WGen вывести данные из дельты штата s или основной Monadm, но они уводят нас еще дальше от основных абстракций. Основными абстракциями являются Arrow а также Category, которые знают только о a bи не про s e m,

Вот пример очень простой программы, обеспечивающей ввод в качестве ввода a, double это самый внешний провод программы. 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

Я только что решил это способом Arrow, так что это может быть более сложным. Вы можете прочитать мои сообщения, если хотите. Клейсли Стрелка в Netwire 5? и консольная интерактивность в Netwire?, Второй пост имеет полную интерактивную программу

Во-первых, это нужно, чтобы поднять функции Клейсли (то есть 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)
Другие вопросы по тегам