I am new to Haskell, and I have been playing around with Arrows. I would like to write a tool that can programmatically "disassemble" a previously constructed Arrow. As a potential application, imagine a function that takes in an Arrow and returns a directed graph that represents all the concatenations, splits, fan-outs, etc.
E.g., (f &&& g) >>> h yields something like
----- f ----
---| |--- h -----
----- g ----
I initially thought I might be able to do this via pattern matching, as in the simple below (adapted from haskell.org Arrow tutorial), but it did not work.
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
All my attempts to do this by defining my own types (i.e., a parameterized type that includes types of constituent children as well) have also failed.
Is there some way to "pull apart" the components of an arrow once it has been constructed?