解构Haskell中的箭头

时间:2014-12-24 17:41:10

标签: haskell arrows

我是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

我通过定义自己的类型(即包含成分子类型的参数化类型)的所有尝试都失败了。

有没有办法在箭头构造完成后“拉开”箭头的组件?

2 个答案:

答案 0 :(得分:5)

你可以制作一个像树一样的自由箭头,这样你就可以检查它的结构。或者将其降低到底层箭头。一个例子是另一个SO问题:Useful operations on free arrows

答案 1 :(得分:1)

答案通常不会,因为扇出和组合以及其他箭头操作符是函数,而不是构造函数。你可以将树分开,比如树,因为从其他树中组合树会保留用于执行组合的构造函数,然后Haskell可以对它们进行模式匹配。但是,并不能保证组成箭头会保留用于执行构图的扇出和构图。这就像添加2 + 3然后试图将5分开。