Haskell 中带反馈回路的时序电路
Sequential circuit with feedack loop in Haskell
我想在 Haskell 中表示具有以下行为的电路:
电路有两个输入:
- 一个数据输入
- 和一个开关输入
和一个输出。
- 当开关=
True
则输出t=输入t
- 当switch=
False
时,输出t=输出t-1
我需要一种方法来表示反馈回路和状态。
我知道有几个库为这类事情提供抽象,但它们对我来说就像魔法一样。
有没有简单的建模方法?
编辑:
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
我使用流来表示信号,并在 s 中显式携带状态。但是,如果我想即时提取(查看)输出流中的元素怎么办?
看起来像是 State Monad 可以解决的问题,但我找不到表示它的方法。
它的价值:这个问题非常适合 Haskell 的一些独特而强大的抽象,例如 Monad
和 Arrow
。但是这些需要时间和经验来学习,而且我从你的措辞中猜测你对它们不是很熟悉。如果你留在Haskell,我建议以后再重新审视这个问题以获得启示。我不会花更多的时间在这些事情上。
您可以简单地通过无限列表对离散时变信号建模:
type Signal a = [a]
zeroS, oneS :: Signal Bool
zeroS = repeat False
oneS = repeat True
您可以使用 zipWith
逐点组合信号。例如:
andS :: Signal Bool -> Signal Bool -> Signal Bool
andS = zipWith (&&)
ghci> andS zeroS oneS
[False,False,False,False,False,False,False,False,...
您可以通过在列表的开头使用 consing 将信号延迟 1 个时间单位。这需要信号的初始值。
delay :: a -> Signal a -> Signal a
delay x s = x : s
-- or just
-- delay = (:)
在你的问题中,你描述了一个具有这种类型的函数:
circuit :: Signal Bool -> Signal Bool -> Signal Bool
circuit switch input = ...
您可以使用这些概念和递归构建它。祝你好运!
好的,我想我终于明白了如何为此使用 State Monad。
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
circuit
函数可以处理离散输入,而 loopCircuit
可以处理输入流。
res1 = (4,4)
example2 = ([0,0,3],3)
我想在 Haskell 中表示具有以下行为的电路:
电路有两个输入:
- 一个数据输入
- 和一个开关输入
和一个输出。
- 当开关=
True
则输出t=输入t - 当switch=
False
时,输出t=输出t-1
我需要一种方法来表示反馈回路和状态。
我知道有几个库为这类事情提供抽象,但它们对我来说就像魔法一样。
有没有简单的建模方法?
编辑:
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
我使用流来表示信号,并在 s 中显式携带状态。但是,如果我想即时提取(查看)输出流中的元素怎么办?
看起来像是 State Monad 可以解决的问题,但我找不到表示它的方法。
它的价值:这个问题非常适合 Haskell 的一些独特而强大的抽象,例如 Monad
和 Arrow
。但是这些需要时间和经验来学习,而且我从你的措辞中猜测你对它们不是很熟悉。如果你留在Haskell,我建议以后再重新审视这个问题以获得启示。我不会花更多的时间在这些事情上。
您可以简单地通过无限列表对离散时变信号建模:
type Signal a = [a]
zeroS, oneS :: Signal Bool
zeroS = repeat False
oneS = repeat True
您可以使用 zipWith
逐点组合信号。例如:
andS :: Signal Bool -> Signal Bool -> Signal Bool
andS = zipWith (&&)
ghci> andS zeroS oneS
[False,False,False,False,False,False,False,False,...
您可以通过在列表的开头使用 consing 将信号延迟 1 个时间单位。这需要信号的初始值。
delay :: a -> Signal a -> Signal a
delay x s = x : s
-- or just
-- delay = (:)
在你的问题中,你描述了一个具有这种类型的函数:
circuit :: Signal Bool -> Signal Bool -> Signal Bool
circuit switch input = ...
您可以使用这些概念和递归构建它。祝你好运!
好的,我想我终于明白了如何为此使用 State Monad。
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
circuit
函数可以处理离散输入,而 loopCircuit
可以处理输入流。
res1 = (4,4)
example2 = ([0,0,3],3)