用箭头建模电路
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
就可以了,不过这里不在话下)
然后,我们可以使用一些常见的逻辑等价得到andGate
、nandGate
和xorGate
:
-- 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)
我有:
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
就可以了,不过这里不在话下)
然后,我们可以使用一些常见的逻辑等价得到andGate
、nandGate
和xorGate
:
-- 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)