4

I have a

foreign export stdcall tick :: Integer -> Float -> Float -> IO Int

On each invocation of this function, I wish to pass its arguments into a set of pipes from the haskell pipes library.

Between the invocations I don't want the pipes to forget the minimum and maximum of the arguments of the last 10 invocations.

How should I do this?

  • As a suggestion, you might be able to use `MVar`s to retain internal state which are held in the pipes, and everything already has to occur in the `IO` monad judging from your `tick` function's signature. It's hard to say without a minimum working example. – bheklilr Dec 11 '13 at 04:35
  • Not sure what exactly you want. You don't *pass* values to pipe, rather you create a pipeline from pipes and then run that pipeline using runEffect. – Ankur Dec 11 '13 at 04:42
  • 1
    I want something like Pipes.Network.TCP.fromSocket but instead of getting data from a Socket, it is a Producer which yields data from all the foreign invocations of tick since the last yield of the Producer. – Edwin Jose Palathinkal Dec 11 '13 at 06:09
  • There seems to be two parts to your question; how to retain the last 10 invocations, and how to use the Haskell pipes library. Which one are you trying to do? And which "pipes" are you trying to use? Perhaps if you told us what problem you are actually trying to solve? – Paul Johnson Dec 11 '13 at 07:50

1 Answers1

1

This is one of many things that pipes-concurrency is designed to do. What you do is spawn a buffer and every time you call the derived tick function it will stuff its arguments inside that buffer. Then you can have a pipe stream everything that comes out of that buffer.

import Control.Concurrent.Async
import Pipes
import Pipes.Concurrent
import qualified Pipes.Prelude as P

-- Your FFI tick function, which we will wrap with a derived function
ffi_tick :: Integer -> Float -> Float -> IO Int
ffi_tick _ _ _ = return 0

-- A data structure just to simplify the types
-- In theory I could have just used a tuple
data Ticker = Ticker
    { _tick  :: Integer -> Float -> Float -> IO Int
    , _input :: Input (Integer, Float, Float)
    }

-- This is in charge of buffer initialization and deriving the new
-- tick function
makeTicker :: IO Ticker
makeTicker = do
    (output, input) <- spawn Unbounded
    let tick x y z = do
            atomically $ send output (x, y, z)
            ffi_tick x y z
    return (Ticker tick input)

-- This is example code showing how you would use it    
main = do
    Ticker tick input <- makeTicker
    a <- async $ runEffect $ fromInput input >-> P.print
    tick 1 2.0 3.0
    tick 4 5.0 6.0
    tick 7 8.0 9.0
    wait a
Gabriella Gonzalez
  • 34,863
  • 3
  • 77
  • 135
  • I hope you didn't overlook the fact that my tick function is a foreign export stdcall. It is meant to be invoked from another process not from within our main. The code that contains the foreign export function is going to be compiled into a DLL. – Edwin Jose Palathinkal Dec 12 '13 at 14:54