Getting input into Netwire programs

后端 未结 2 2248
长情又很酷
长情又很酷 2021-02-20 04:37

I\'m getting started with Netwire version 5.

I have no problem writing all the wires I want to transform my inputs into my outputs.

Now the time has come to writ

相关标签:
2条回答
  • 2021-02-20 05:25

    I just solved this in an Arrow way, so this might be more composible. You can read my posts if you like. Kleisli Arrow in Netwire 5? and Console interactivity in Netwire?. The second post has a complete interactive program

    First, you need this to lift Kleisli functions (That is, anything 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
    

    Then, assuming you want to get characters from terminal, you can lift hGetChar by doing this:

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

    I haven't tested this runWire function (I just stripped code off from my previous posts), but it should run your wires:

    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'
    

    You can compose the input wire wherever you like like any other Wires or Arrows. In my example, I did this (don't just copy, other parts of the program are different):

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

    Or, one-liner:

    mainWire = inputWire >>> (quitWire &&& outputWire) >>> arr (\(q,_) -> q)
    
    0 讨论(0)
  • The simplest way to put data into a Wire s e m a b is via the input a. It's possible, through the use of WPure or WGen to get data out of the state delta s or the underlying Monad m, but these take us further away from the main abstractions. The main abstractions are Arrow and Category, which only know about a b, and not about s e m.

    Here's an example of a very simple program, providing input as the input a. double is the outermost wire of the program. repl is a small read-eval-print loop that calls stepWire to run the wire.

    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
    

    Notice that we pass in the time difference to stepWire, not the total elapsed time. We can check that this is the correct thing to do by running a different top-level wire.

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

    Which has the desired output:

    a
    1
    b
    2
    c
    3
    
    0 讨论(0)
提交回复
热议问题