Search code examples
loopshaskellsequentialfeedbackcircuit

Sequential circuit with feedack loop in Haskell


I would like to represent a circuit with the following behaviour in Haskell:

The circuit has two inputs :

  • a data input
  • and a switch input

and one output.

  • When the switch = True then output t = input t
  • when switch = False, output t = output t-1

I need a way to represent the feedback loop, and the state.

I know there is several libraries providing abstractions for this sort of thing, but they look like magic to me.

Is there a simple way to model this?

Edit:

type Signal a = [a]

type Input   = Signal Int
type Output  = Signal Int
type State   = Int
type Switch = Signal Bool

delay :: a -> Signal a -> Signal a
delay = (:)

circuit :: State -> Input -> Switch -> Output
circuit s (i:is) (True:bs) =  i : circuit i is bs
circuit s (i:is) (False:bs) = s : circuit s is bs

I used streams to represent the signals, and I carry the state around explicitly in s. But what if I wanted to extract (look at) the elements in the output stream on the fly?

It looks like a problem that the State Monad would solve but I can't find a way to represent it.


Solution

  • Ok I think I finally got how to use the State Monad for this.

    Import Control.Monad.State
    
    type Stored a = a
    type Input a = a
    type Output a = a
    type Switch = Bool
    
    circuit :: Input a -> Switch -> State (Output a) (Stored a)
    circuit input switch = 
        do store <- get
           if switch
           then put input >> return input
           else return store
    
    example1 = do circuit 0 False
                  circuit 2 False
                  circuit 3 False
    
    res1 = runState example1 $ 4
    
    loopCircuit :: [(Input a, Switch)] -> State (Output a) [(Stored a)]
    loopCircuit [] = return []
    loopCircuit ((i,s):xs) = 
        do v  <- circuit i s 
           vs <- loopCircuit xs
           return (v:vs)
    
    example2 = runState (loopCircuit [(0,True),(2,False),(3,True)]) 4
    

    The circuit function can work on discrete inputs, while loopCircuit can work on a stream of inputs.

    res1 = (4,4)
    example2 = ([0,0,3],3)