Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Deconstructing Arrows in Haskell

Tags:

haskell

arrows

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?

like image 575
jadaska Avatar asked Dec 24 '14 17:12

jadaska


People also ask

What does -> mean in Haskell?

(->) is often called the "function arrow" or "function type constructor", and while it does have some special syntax, there's not that much special about it. It's essentially an infix type operator. Give it two types, and it gives you the type of functions between those types.

What are arrows in haskell?

The Arrow (either (->) or MyArr ) is an abstraction of a computation. For a function b -> c , b is the input and c is the output. For a MyArr b c , b is the input and c is the output. 2) To actually run an arrow computation, you use a function specific to your arrow type.


2 Answers

You can make a free arrow, which is like a tree, so you can inspect its structure. Or lower it to underlying arrow. One example is in the other SO question: Useful operations on free arrows

like image 61
phadej Avatar answered Oct 12 '22 20:10

phadej


The answer is going to be no in general, because fanout and composition and the other arrow operators are functions, not constructors. You can "pull apart", say, a tree, because composing trees out of other trees preserves the constructors used to perform the composition, and then Haskell can pattern-match on them. But there's no guarantee that composing arrows will preserve the fanouts and compositions used to perform the composition. It's like adding 2+3 and then trying to pull apart the 5 later.

like image 37
Peter Milley Avatar answered Oct 12 '22 19:10

Peter Milley