双向箭头

时间:2017-02-13 15:18:12

标签: haskell arrows

我试图使用箭头捕获对称数据处理管道,并且想知道是否可以进行双向合成。

Control.Arrow公开以下内容

-- | Left to right composition
(>>>) :: Category cat => cat a b -> cat b c -> cat a c 

-- | Right to left composition
(<<<) :: Category cat => cat b c -> cat a b -> cat a c 

我喜欢什么,但无法解决如何表达双向组合。类型就像。

(<^>) :: Category cat => cat (a,y) (b,z) -> cat (b,x) (c,y) -> cat (a,x) (c,z) 

其中每对的第一个元素是从左到右组成,第二个元素是从右到左组成。

2 个答案:

答案 0 :(得分:5)

这是一个涉及前向和后向功能对的类别示例。

{-# LANGUAGE TypeOperators, GADTs #-}

import Prelude hiding ((.))
import Data.Category
import Data.Category.Product

type C = (->) :**: (Op (->))

以上说明C (a,b) (c,d)与同义(a->c, d->b)同构。对&#34;撰写&#34;在自然方式的类别中:前向函数是向前组成的,向后函数是向后组成的。

以下是两个例子:

f :: C (String, Bool) (Int, Char)
f = length :**: Op (=='a')

注意向后函数必须如何包含在Op中(属于&#34;对面&#34;类别)。

g :: C (Int, Char) ([Int], Maybe Char)
g = (\x->[x,x]) :**: Op (maybe 'X' id)

注意&#34;来源&#34; g是&#34;目标&#34; f。这确保了组合成为可能。

composed :: C (String, Bool) ([Int], Maybe Char)
composed = g . f

test :: ([Int], Bool)
test = case composed of
   (forward :**: Op backward) -> (forward "abcde", backward Nothing)
-- result: ([5,5],False)

在更实际的方面,请注意Data.CategoryControl.Category是不同的野兽:-(并且问题中提到的Control.Arrow库使用后者。

仍然可以为Op定义:**:Control.Category。也许它已经在某个地方进行过hackage(?)。

答案 1 :(得分:2)

一些进一步的方法,最好记录为单独的答案。

第一个强加了ArrowLoop的附加约束,并使用递归箭头do表示法定义。

然而,从数据流的角度来看,没有发生递归。

(<->) ∷ (ArrowLoop a) ⇒ a (b,f) (c,g) → a (c,e) (d,f) → a (b,e) (d,g)
(<->) f1 f2 = proc (b, e) → do
  rec
    (c,g) ← f1 ↢ (b,f)
    (d,f) ← f2 ↢ (c,e)
  returnA ↢ (d,g)

同样可以定义为

(<->) ∷ (ArrowLoop a) ⇒ a (b,f) (c,g) → a (c,e) (d,f) → a (b,e) (d,g)
(<->) f1 f2 = proc (b, e) → do
  rec
    (d,f) ← f2 ↢ (c,e)
    (c,g) ← f1 ↢ (b,f)
  returnA ↢ (d,g)

第二种方法不是:如果这是一个理智的事情,我还没有解决。

(<->) ∷ (Arrow a) ⇒ a (b,f) (c,g) → a (c,e) (d,f) → a (b,e) (d,g)
(<->) f1 f2 = proc (b, e) → do
  (c,_) ← f1 ↢ (b,undefined)
  (d,_) ← f2 ↢ (c,undefined)
  (_,f) ← f2 ↢ (undefined,e)
  (_,g) ← f1 ↢ (undefined,f)
  returnA ↢ (d,g)

以下与第二种方法相同,但在组成函数方面明确定义。

(<->) ∷ (Arrow a) ⇒ a (b,f) (c,g) → a (c,e) (d,f) → a (b,e) (d,g)
(<->) f g =
  let toFst x = (x,undefined)
      toSnd x = (undefined,x)
  in
    (arr toFst ⋙ f ⋙ arr fst ⋙ arr toFst ⋙ g ⋙ arr fst) ⁂
    (arr snd ⋘ f ⋘ arr toSnd ⋘ arr snd ⋘ g ⋘ arr toSnd)