用箭头建模电路

Modeling a circuit with arrows

我有:

class Arrow circ ⇒ Circuit circ where
    wire    :: circ Bool Bool
    notGate :: circ Bool Bool
    orGate  :: circ (Bool , Bool ) Bool

    wire = id
    notGate = arr not
    orGate = arr $ uncurry (||)

我要实施:

-- A and B
andGate :: Circuit circ ⇒ circ (Bool , Bool ) Bool
-- not (A and B)
nandGate :: Circuit circ ⇒ circ (Bool , Bool ) Bool
-- A xor B
xorGate :: Circuit circ ⇒ circ (Bool , Bool ) Bool

我不想用(arr and)这么简单的东西,而是结合已有的功能。我无法理解如何像处理函数那样组合箭头。

谢谢。

推荐你看看Control.Arrow, in particular (***), (&&&), and (>>>). This tutorial也确实不错。

  • (***) 允许您取两个箭头并将它们并排放入一个具有输入和输出(作为元组)的箭头中:

    (***) :: Arrow a => a b c -> a b' c' -> a (b, b') (c, c')
    
  • (&&&) 让你再次组合两个箭头并得到它们输出的元组,但这次两个箭头都将消耗 same输入:

    (&&&) :: Arrow a => a b c -> a b c' -> a b (c, c')
    
  • (>>>) 可让您排列(组合)两个箭头。这与函数组合非常相似。事实上,(>>>) 只是 Control.Category 的广义 (.),其参数翻转了。

    (>>>) :: Arrow a => a b c -> a c d -> a b d
    

    (其实约束条件只要Category就可以了,不过这里不在话下)

然后,我们可以使用一些常见的逻辑等价得到andGatenandGatexorGate:

-- Use (x NAND y) === ((NOT x) OR (NOT y))
nandGate :: Circuit circ => circ (Bool, Bool) Bool
nandGate = (notGate *** notGate) >>> orGate

-- Use (x NAND y) === (NOT (x NAND y))
andGate :: Circuit circ => circ (Bool, Bool) Bool
andGate = nandGate >>> notGate

-- Use (x XOR y) === ((x OR y) AND (x NAND y))
xorGate :: Circuit circ => circ (Bool, Bool) Bool
xorGate = (orGate &&& nandGate) >>> andGate

-XArrows

旁边

有一个非常简洁的语法扩展,让您可以使用类似 do 的特殊符号来编写 Arrow。这比神秘的 Control.Arrow 运算符更具可读性,尤其是当你有一堆箭头相互作用时。

{-# LANGUAGE Arrows #-}

 nandGate :: Circuit circ => circ (Bool , Bool ) Bool
 nandGate = proc (x,y) -> do
              x' <- notGate -< x
              y' <- notGate -< y
              orGate -< (x',y')

 andGate :: Circuit circ => circ (Bool, Bool) Bool
 andGate = proc (x,y) -> do
              z <- nandGate -< (x,y)
              notGate -< z

 xorGate :: Circuit circ => circ (Bool, Bool) Bool
 xorGate = proc (x,y) -> do
              z <- orGate -< (x,y)
              w <- nandGate -< (x,y)
              andGate -< (z,w)