我想在Haskell中表示具有以下行为的电路:
电路有两个输入:
和一个输出。
True
然后输出 t = input t False
时,输出 t = output 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中明确地携带状态。但是如果我想在运行中提取(查看)输出流中的元素呢?
状态Monad会解决这个问题,但我找不到代表它的方法。
答案 0 :(得分:7)
对于它的价值:这个问题非常适合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,...
您可以通过列表开头的信号将信号延迟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 = ...
您可以使用这些概念和递归来构建。祝你好运!
答案 1 :(得分:0)
好的,我想我终于得到了如何使用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)