我正在尝试使用箭头捕获对称数据处理管道,并且想知道双向组合是否可行.
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
Run Code Online (Sandbox Code Playgroud)
我想要什么,但无法解决如何表达是双向组合.类型是这样的.
(<^>) :: Category cat => cat (a,y) (b,z) -> cat (b,x) (c,y) -> cat (a,x) (c,z)
Run Code Online (Sandbox Code Playgroud)
其中每对的第一个元素是从左到右组成,第二个元素是从右到左组成.
这是一个涉及前向和后向功能对的类别示例.
{-# LANGUAGE TypeOperators, GADTs #-}
import Prelude hiding ((.))
import Data.Category
import Data.Category.Product
type C = (->) :**: (Op (->))
Run Code Online (Sandbox Code Playgroud)
上述状态C (a,b) (c,d)与一对同构(a->c, d->b).对以自然方式在类别中"组合":向前功能向前组成,向后功能向后组成.
这是两个例子:
f :: C (String, Bool) (Int, Char)
f = length :**: Op (=='a')
Run Code Online (Sandbox Code Playgroud)
注意向后函数必须如何包装Op(属于"相反"类别).
g :: C (Int, Char) ([Int], Maybe Char)
g = (\x->[x,x]) :**: Op (maybe 'X' id)
Run Code Online (Sandbox Code Playgroud)
注意"源" g的"目标"是什么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)
Run Code Online (Sandbox Code Playgroud)
在一个更实际的方面,请注意Data.Category并且Control.Category是不同的野兽:-(并且Control.Arrow问题中提到的库使用后者.
不过,这应该是可以定义Op并:**:进行Control.Category为好.也许它已经在hackage某处(?).