我是Haskell的新手,我一直在玩Arrows。我想写一个工具,可以编程“拆解”以前构建的箭头。作为一个潜在的应用程序,想象一个函数,它接收一个箭头并返回一个有向图,代表所有连接,分裂,扇出等。
例如,(f&&& g)>>> h产生类似的东西 ----- f ----
---| |--- h -----
----- g ----
我最初认为我可以通过模式匹配来实现这一点,如下面的简单(改编自haskell.org箭头教程),但它不起作用。
module Main(main) where
import Control.Arrow
import Control.Category
import Prelude hiding (id, (.))
newtype SimpleFunc a b = SimpleFunc {runF :: (a -> b)}
instance Arrow SimpleFunc where
arr f = SimpleFunc f
first (SimpleFunc f) = SimpleFunc (mapFst f) where
mapFst g (a,b) = (g a, b)
second (SimpleFunc f) = SimpleFunc (mapSnd f) where
mapSnd g (a,b) = (a, g b)
instance Category SimpleFunc where
(SimpleFunc g) . (SimpleFunc f) = SimpleFunc (g . f)
id = arr id
f,g :: SimpleFunc Int Int
f = arr (\x -> x - 5)
g = arr (\x -> 3*x + 1)
h1 :: SimpleFunc Int Int
h1 = f >>> g
h2 :: SimpleFunc Int (Int, Int)
h2 = f &&& g
# It would be great if I something like this worked
is_split :: SimpleFunc a b -> Bool
is_split (a1 >>> a2) = False
is_split (a1 &&& a2) = True
....
is_split h2 -- evaluates to True
is_split h1 -- evaluates to False
我通过定义自己的类型(即包含成分子类型的参数化类型)的所有尝试都失败了。
有没有办法在箭头构造完成后“拉开”箭头的组件?
答案 0 :(得分:5)
你可以制作一个像树一样的自由箭头,这样你就可以检查它的结构。或者将其降低到底层箭头。一个例子是另一个SO问题:Useful operations on free arrows
答案 1 :(得分:1)
答案通常不会,因为扇出和组合以及其他箭头操作符是函数,而不是构造函数。你可以将树分开,比如树,因为从其他树中组合树会保留用于执行组合的构造函数,然后Haskell可以对它们进行模式匹配。但是,并不能保证组成箭头会保留用于执行构图的扇出和构图。这就像添加2 + 3然后试图将5分开。