packages feed

needle (empty) → 0.1.0.0

raw patch · 7 files changed

+812/−0 lines, 7 filesdep +basedep +containersdep +haskell-src-metasetup-changed

Dependencies added: base, containers, haskell-src-meta, mtl, parsec, parsec-extra, template-haskell, text, vector

Files

+ Control/Arrow/Needle.hs view
@@ -0,0 +1,63 @@+{-|+Module      : Control.Arrow.Needle+Description : ASCII-fied arrow notation.+Copyright   : (c) 2014 Josh Kirklin+License     : MIT+Maintainer  : jjvk2@cam.ac.uk++Needle is a domain specific language for ASCII-fied arrow notation. This module enables the use of needle within Haskell by making use of Template Haskell.++In needle, data travels along rails. There are three types of rail, and data travels in different directions on each:++    [@=@] left to right+    [@\\@] down+    [@/@] up++Data enters a rail with @}@, and exits with @>@.++When rails are joined, their contents are concatenated. When rails are split, their contents are duplicated.++An external arrow can be embedded in a rail by enclosing it between a @{@ and a @}@.++Inputs and outputs of rails can be asigned labels with a @:@.++Rails can cross one another, if one of the rails has gone \'underground\' by entering a \'tunnel\'. A tunnel entrance is specified by a @)@, and a tunnel exit is specified by a @(@.++Most questions should be answered by a short example:++> import Control.Arrow.Needle+>+> nTest :: (Int, Int, Int) -> (Int, (Int, Int, Int))+> nTest = [nd|+>                         aLabel:==={div 2}===\+>     }====\                                  \+>          {uncurry (+)}==\=================) \ (==>+>     }====/              \                   \+>                         \                   \=={nTriple}=>+>                         \               +>                      }=={uncurry (-)}====:aLabel+> |]+> +> nTriple = [nd|+>     }==\==>+>        \==>+>        \==>+> |]++>>> nTest (3,2,1)+(5,(-1,-1,-1))++-}++module Control.Arrow.Needle (+    nd+  , ndFile+    -- * Reexported for your convenience+  , module Control.Arrow+) where+++import Control.Arrow++import Control.Arrow.Needle.TH (nd, ndFile)+
+ Control/Arrow/Needle/Internal/UnevenGrid.hs view
@@ -0,0 +1,276 @@+{-|+Module      : Control.Arrow.Needle.Internal.UnevenGrid+Description : Data structure used in parsing needle diagrams+Copyright   : (c) Josh Kirklin+License     : MIT+Maintainer  : jjvk2@cam.ac.uk++Implements a 'Grid' data structure which can be examined and moved around with a monad 'GridExamine', used in needle parsing.+-}++{-# LANGUAGE DeriveFunctor, OverloadedLists, GeneralizedNewtypeDeriving, TupleSections#-}++module Control.Arrow.Needle.Internal.UnevenGrid (+    -- * Grids+    Grid ()+  , grid+  , prettyGrid+  , height+  , GridPosition+  , (!!?)+  , findPositions+    -- * Examining+  , GridExamine ()+  , gridExamine+  , branch+  , getGrid+  , getPosition+  , putPosition+  , modifyPosition+  , width+    -- ** Moving and accessing+  , hereGet+  , leftGet+  , rightGet+  , lUpGet+  , lDownGet+  , rUpGet+  , rDownGet+  ) where++import Prelude as Pre++import Data.Foldable as F++import Data.Vector as V+import Data.Maybe +import Data.List +import Data.Sequence as S++import Control.Applicative+import Control.Monad.State as St+import Control.Monad.Reader++import Control.Arrow++-- | A 'Grid' is a list of rows, the elements of which are not necessarily +-- aligned, with the exception that the left edge of the grid is aligned.+--+-- So for example, the following is a valid shape for a 'Grid':+--+-- >  ____________+-- > |___|___|_|__|+-- > |__|_|_|__|_|__+-- > |_|______|_____|+-- >+--++newtype Grid e = Grid { rows :: Vector (GridRow e) }+    deriving (Eq, Functor, Show)++newtype GridRow e = GridRow { elements :: Vector (GridElem e) } +    deriving (Eq, Functor, Show)++fromLeft :: GridRow e -> Int -> Maybe Int+fromLeft (GridRow row) n = V.findIndex ((> n) . end) $ row++data GridElem e = GridElem {+    end :: Int+  , unwrap :: e+} deriving (Eq, Functor, Show)++type GridPosition = (Int, Int)++-- | Generate a 'Grid' from a list of rows of elements and widths.++grid :: [[(e, Int)]] -> Grid e+grid rs = Grid . V.fromList . Pre.map (GridRow . V.fromList) $ gridElems+  where+    widths = Pre.map (Pre.map snd) rs+    es = Pre.map (Pre.map fst) rs+    f a = Pre.zipWith (+) (0 : f a) a+    ends = Pre.map f widths+    gridElems = Pre.zipWith (Pre.zipWith GridElem) ends es++-- | Pretty print a grid++prettyGrid :: (e -> Int -> String) -> Grid e -> String+prettyGrid eShow grid = unlines . Pre.map Pre.concat $ lShowns+  where+    untyped = V.map elements . rows $ grid+    widths = V.map ((\a -> V.zipWith (-) a (0 `cons` a)) . V.map end) untyped+    unwrappeds = V.map (V.map unwrap) untyped+    showns = V.zipWith (V.zipWith eShow) unwrappeds widths+    lShowns = Pre.map V.toList . V.toList $ showns++-- | Get the grid height++height :: Grid e -> Int+height = V.length . rows++-- | Get the element at a certain position in the grid. The top left block is+-- in the (0,0) position.++(!!?) :: Grid e -> GridPosition -> Maybe e+(!!?) grid (rowPos, elemPos) = do+    row <- rows grid !? rowPos+    element <- elements row !? elemPos+    return $ unwrap element++-- | Return a list of positions satisfying a predicate in a grid, in reading order.++findPositions :: (e -> Bool) -> Grid e -> [GridPosition]+findPositions pred = V.toList . V.concat . V.toList . V.map (\(i,r) -> V.map (i,) . V.findIndices (pred . unwrap) . elements $ r) . indexed . rows+++-- | A monad for examining a grid.++newtype GridExamine e a = GridExamine (StateT GridPosition (Reader (Grid e)) a)+    deriving (Functor, Applicative, Monad)++-- | Run a grid examination. A start position must be specified.++gridExamine :: Grid e -> GridPosition -> GridExamine e a -> a+gridExamine grid start (GridExamine s) = runReader (evalStateT s start) grid++-- | Get the entire grid.++getGrid :: GridExamine e (Grid e)+getGrid = GridExamine (lift ask)++-- | Get the current position in the grid.++getPosition :: GridExamine e GridPosition+getPosition = GridExamine get++-- | Set the current position in the grid. +-- This is unsafe -- an in bounds check is NOT performed.++putPosition :: GridPosition -> GridExamine e ()+putPosition = GridExamine . put++-- | Modify the current position in the grid.+-- This is unsafe -- an in bounds check is NOT performed.++modifyPosition :: (GridPosition -> GridPosition) -> GridExamine e ()+modifyPosition f = GridExamine (St.modify f)++here :: GridExamine e (Maybe (GridElem e))+here = do+    grid <- getGrid+    (rowPos, elemPos) <- getPosition+    return $ do+        row <- rows grid !? rowPos+        element <- elements row !? elemPos+        return element++-- | Get the element at the current position.++hereGet :: GridExamine e (Maybe e)+hereGet = do+    element <- here+    return $ fmap unwrap element++-- | Move to and return the grid element to the left. If there is no element to +-- the left, returns Nothing.++leftGet :: GridExamine e (Maybe e)+leftGet = do+    (rowPos, elemPos) <- getPosition+    if elemPos > 0 +        then putPosition (rowPos, elemPos - 1) >> (hereGet)+        else return Nothing++-- | Move to and return the grid element to the right. If there is no element to +-- the right, returns Nothing.++rightGet :: GridExamine e (Maybe e)+rightGet = do+    grid <- getGrid+    (rowPos, elemPos) <- getPosition+    fromMaybe (return Nothing) $ do+        row <- rows grid !? elemPos +        element <- elements row !? (elemPos + 1)+        return $ putPosition (rowPos, elemPos + 1) >> return (Just $ unwrap element)++-- | Move to and return the grid element above the column a certain distance +-- from the right edge of the current element. If there is no such element, returns +-- Nothing.++rUpGet :: Int -> GridExamine e (Maybe e)+rUpGet n = do+    grid <- getGrid+    mCurrentElement <- here+    (rowPos, _) <- getPosition+    fromMaybe (return Nothing) $ do+        currentElement <- mCurrentElement+        newRow <- rows grid !? (rowPos - 1)+        i <- fromLeft newRow (end currentElement - 1 - n)+        return $ putPosition (rowPos - 1, i) >> hereGet++-- | Move to and return the grid element below the column a certain distance +-- from the right edge of the current element. If there is no such element, returns +-- Nothing.++rDownGet :: Int -> GridExamine e (Maybe e)+rDownGet n = do+    grid <- getGrid+    mCurrentElement <- here+    (rowPos, _) <- getPosition+    fromMaybe (return Nothing) $ do+        currentElement <- mCurrentElement+        newRow <- rows grid !? (rowPos + 1)+        i <- fromLeft newRow (end currentElement - 1 - n)+        return $ putPosition (rowPos + 1, i) >> hereGet++-- | Move to and return the grid element above the column a certain distance +-- from the left edge of the current element. If there is no such element, returns +-- Nothing.++lUpGet :: Int -> GridExamine e (Maybe e)+lUpGet n = do+    grid <- getGrid+    (rowPos, elemPos) <- getPosition+    fromMaybe (return Nothing) $ do+        row <- rows grid !? rowPos+        let start = fromMaybe 0 $ end <$> (elements row !? (elemPos - 1))+        newRow <- rows grid !? (rowPos - 1)+        i <- fromLeft newRow (start + n)+        return $ putPosition (rowPos - 1, i) >> hereGet++-- | Move to and return the grid element below the column a certain distance +-- from the left edge of the current element. If there is no such element, returns +-- Nothing.++lDownGet :: Int -> GridExamine e (Maybe e)+lDownGet n = do+    grid <- getGrid+    (rowPos, elemPos) <- getPosition+    fromMaybe (return Nothing) $ do+        row <- rows grid !? rowPos+        let start = fromMaybe 0 $ end <$> (elements row !? (elemPos - 1))+        newRow <- rows grid !? (rowPos + 1)+        i <- fromLeft newRow (start + n)+        return $ putPosition (rowPos + 1, i) >> hereGet++-- | Branch an examination, i.e. perform it and then return to the original position.++branch :: GridExamine e a -> GridExamine e a+branch ge = do+    pos <- getPosition+    x <- ge+    putPosition pos+    return x++-- | The width of the current element++width :: GridExamine e (Maybe Int)+width = do+    grid <- getGrid+    (rowPos, elemPos) <- getPosition+    mh <- here+    return $ do+        h <- mh+        row <- rows grid !? rowPos+        let start = fromMaybe 0 $ end <$> (elements row !? (elemPos - 1))+        return (end h - start)
+ Control/Arrow/Needle/Parse.hs view
@@ -0,0 +1,308 @@+{-|+Module      : Control.Arrow.Needle.Parse+Description : Parsing needle diagrams+Copyright   : (c) 2014 Josh Kirklin+License     : MIT+Maintainer  : jjvk2@cam.ac.uk++This module's main export is 'parseNeedle', which parses a needle diagram into a `NeedleArrow`.+-}++module Control.Arrow.Needle.Parse (+  -- * Parsing needles+    NeedleArrow (..)+  , parseNeedle+  -- * Errors+  , NeedleError (..)+  , presentNeedleError+  ) where++import qualified Data.Map.Strict as M++import qualified Data.Text as T+import Data.Maybe+import Data.Either+import Data.Monoid++import Text.Parsec as P+import Text.Parsec.Extra (natural)+import Data.Char++import Control.Monad+import Control.Applicative ((<$>), (<*>))+import Control.Monad.State+import Control.Arrow++import Control.Arrow.Needle.Internal.UnevenGrid as G++--------------------------------+-- Types+--------------------------------++-- | The datatype representing a generic needle arrow.++data NeedleArrow = Input Int Int+                 | Through NeedleArrow T.Text+                 | Join [NeedleArrow]+    deriving (Show, Read, Eq)++-- | The grid element for the first round of parsing.++data NeedleElem = None+                | Track+                | In Int Int+                | Out+                | LabelIn T.Text+                | LabelOut T.Text+                | ExtArrow T.Text+                | Switch Direction+                | TunnelEntrance+                | TunnelExit+    deriving (Show, Read, Eq)++-- | Errors in parsing.++data NeedleError = ParseError String+                 | ConstructionError String++instance Show NeedleError where+    show = presentNeedleError++-- | Present the error.++presentNeedleError :: NeedleError -> String+presentNeedleError (ParseError s) = "Needle parse error:\n"++s+presentNeedleError (ConstructionError s) = "Needle construction error:\n"++s++data Direction = Up | Down+    deriving (Show, Read, Eq)++type NeedleGrid = Grid NeedleElem++--------------------------------+-- String -> NeedleArrow+--------------------------------++-- | Parse a string to a needle++parseNeedle :: String -> Either NeedleError NeedleArrow+parseNeedle = parseNeedleGrid >=> gridArrow++--------------------------------+-- NeedleGrid -> NeedleArrow+--------------------------------++gridArrow :: NeedleGrid -> Either NeedleError NeedleArrow+gridArrow grid = do+        os <- mapM (arrowToPosition grid) $ outputPositions grid+        maybe (Left $ ConstructionError "No outputs") return $ arrowJoin os++outputPositions :: NeedleGrid -> [GridPosition]+outputPositions = findPositions (== Out)++findLabelOutPosition :: T.Text -> GridExamine NeedleElem (Maybe GridPosition)+findLabelOutPosition t = do+    grid <- getGrid+    return $ listToMaybe (findPositions (== (LabelOut t)) grid)++arrowJoin :: [NeedleArrow] -> Maybe NeedleArrow+arrowJoin [] = Nothing+arrowJoin [a] = Just a+arrowJoin as = Just $ Join as++arrowToPosition :: NeedleGrid -> GridPosition -> Either NeedleError NeedleArrow+arrowToPosition grid pos = gridExamine grid pos go+  where+    err = return . Left . ConstructionError+    success = return . Right+    +    tryPath path = branch $ do+        mp <- path+        case mp of+            Nothing -> err "Nothing on this path"+            Just _ -> go++    go = do+        mh <- hereGet+        case mh of+            Nothing -> err "Position not in grid"+            Just h -> case h of+                None -> err "Arrow from nothing"+                Track -> do+                    w <- fromJust <$> width+                    ups <- forM [0 .. (w - 1)] $ \n -> tryPath $ do+                        e <- lUpGet n+                        return $ mfilter (== (Switch Down)) e+                    downs <- forM [0 .. (w - 1)] $ \n -> tryPath $ do+                        e <- lDownGet n+                        return $ mfilter (== (Switch Up)) e+                    left <- tryPath leftGet+                    let paths = rights $ left : ups ++ downs+                        mJoint = arrowJoin paths+                    case mJoint of+                        Nothing -> do+                            (n, _) <- G.getPosition+                            err $ "Track from nowhere on line " ++ show (n + 1)+                        Just joint -> success joint+                In n m -> success $ Input n m+                Out -> do+                    ml <- leftGet+                    case ml of+                        Just l -> go+                        Nothing -> err "An output has no arrow going into it"+                LabelIn t -> do+                    mlo <- findLabelOutPosition t+                    case mlo of+                        Just lo -> putPosition lo >> go+                        Nothing -> err $ "Found label-in '" ++ T.unpack t ++ "' with no label-out"+                LabelOut t -> do+                    ml <- leftGet+                    case ml of+                        Just l -> go+                        Nothing -> err $ "Label-out '" ++ T.unpack t ++ "' has no arrow going into it"+                ExtArrow t -> do+                    left <- tryPath leftGet+                    up <- tryPath $ do+                        e <- lUpGet 0+                        return $ mfilter (== (Switch Down)) e+                    down <- tryPath $ do+                        e <- lDownGet 0+                        return $ mfilter (== (Switch Up)) e+                    let paths = rights $ [left,up,down]+                        mJoint = arrowJoin paths+                    case mJoint of+                        Nothing -> do+                            (n, _) <- G.getPosition+                            err $ "External arrow '" ++ T.unpack t ++ "' on line " ++ show (n + 1) ++ " has no arrow going into it"+                        Just joint -> success $ Through joint t+                Switch d -> do+                    left <- tryPath leftGet+                    continuing <- tryPath $ do+                        e <- case d of+                            Down -> lUpGet 0+                            Up -> lDownGet 0+                        return $ mfilter (== h) e+                    let paths = rights $ [left, continuing]+                        mJoint = arrowJoin paths+                    case mJoint of+                        Nothing -> do+                            (n, _) <- G.getPosition+                            err $ "Line switch from nowhere on line " ++ (show n)+                        Just joint -> success joint+                TunnelExit -> do+                    let tunnel n = if n == 0 +                            then go+                            else do+                                ml <- leftGet+                                case ml of+                                    Nothing -> do+                                        (n,_) <- G.getPosition+                                        err $ "Tunnel from nowhere on line " ++ (show n)+                                    Just TunnelExit -> tunnel (n+1)+                                    Just TunnelEntrance -> tunnel (n-1)+                                    Just _ -> tunnel n+                    tunnel 1+                TunnelEntrance -> do+                    ml <- leftGet+                    case ml of+                        Nothing -> do+                            (n,_) <- G.getPosition+                            err $ "Tunnel entrance has no arrow going into it on line " ++ (show n)+                        Just _ -> go++--------------------------------+-- String -> NeedleGrid+--------------------------------++-- | Pretty print a needle grid++prettyNeedleGrid :: NeedleGrid -> String+prettyNeedleGrid = prettyGrid prettyElem+  where+    prettyElem None           n = replicate n ' '+    prettyElem Track          n = replicate n '='+    prettyElem (In _ _)       n = replicate (n-1) ' ' ++ "}"+    prettyElem Out            n = ">" ++ replicate (n-1) ' '+    prettyElem (LabelIn t)    n = replicate (n - 1 - length s) ' ' ++ s ++ ":"+      where +        s = T.unpack t+    prettyElem (LabelOut t)   n = ":" ++ s ++ replicate (n - 1 - length s) ' ' +      where +        s = T.unpack t+    prettyElem (ExtArrow t)   n = "{" ++ s ++ replicate (n - 2 - length s) ' ' ++ "}"+      where+        s = T.unpack t+    prettyElem (Switch Up)    n = replicate n '/'+    prettyElem (Switch Down)  n = replicate n '\\'+    prettyElem TunnelEntrance n = replicate n ')'+    prettyElem TunnelExit     n = replicate n '('++-- | Parse a needle grid++parseNeedleGrid :: String -> Either NeedleError NeedleGrid+parseNeedleGrid s = case result of+    Left pe -> Left . ParseError $+            "line " ++ (show . sourceLine . errorPos $ pe) ++ ":\n" +++            ls !! ((sourceLine . errorPos $ pe) - 1) ++ "\n" +++            replicate ((sourceColumn . errorPos $ pe) - 1) ' ' ++ "^"+    Right x -> Right (grid x)+  where+    result = zipWithM parseLine ls [1..]+    ls = lines s+    parseLine l n = runParser (do+        p <- P.getPosition+        setPosition $ setSourceLine p n+        es <- many (withWidth . choice . map try $ elemParsers n)+        optional $ try (string "-- " >> many anyChar)+        eof+        return es) 0 "needle expression" l+    withWidth p = do+        c1 <- sourceColumn <$> P.getPosition+        x <- p+        c2 <- sourceColumn <$> P.getPosition+        return (x, c2 - c1)++    elemParsers n = [+        do+            many1 space+            return None+      , do+            many1 (char '=')+            return Track+      , do+            void (char '}')+            m <- getState+            modifyState (+1)+            return $ In n m+      , do+            void (char '>')+            return Out+      , do+            l <- many1 letter+            spaces+            void (char ':')+            return $ LabelIn (T.pack l)+      , do+            void (char ':')+            spaces+            l <- many1 letter+            return $ LabelOut (T.pack l)+      , do+            void (char '{')+            f <- anyChar+            l <- manyTill anyChar (char '}')+            return $ ExtArrow (T.pack $ f : l)+      , do+            void (char '/')+            return $ Switch Up+      , do+            void (char '\\')+            return $ Switch Down+      , do+            void (char ')')+            return TunnelEntrance+      , do+            void (char '(')+            return TunnelExit+      ]+    
+ Control/Arrow/Needle/TH.hs view
@@ -0,0 +1,109 @@+{-|+Module      : Control.Arrow.Needle.TH+Description : Template Haskell for needle+Copyright   : (c) 2014 Josh Kirklin+License     : MIT+Maintainer  : jjvk2@cam.ac.uk++This module combines the parsing from "Control.Arrow.Needle.Parse" with Template Haskell.+-}++{-# LANGUAGE TemplateHaskell, TupleSections #-}++module Control.Arrow.Needle.TH (+    nd+  , ndFile+  ) where++import Prelude as Pre++import Control.Arrow.Needle.Parse+import Control.Arrow++import Control.Applicative++import Language.Haskell.TH+import Language.Haskell.TH.Quote+import Language.Haskell.Meta++import Data.Either+import Data.Text as T+import Data.Map.Strict as M++-- | The inline needle quasi-quoter.+--+-- > {-# LANGUAGE QuasiQuotes #-}+-- > +-- > exampleArrow :: Num c => (a,b,c) -> (a,a,b,c,c)+-- > exampleArrow = [nd|+-- >    }===========>+-- >       \========>+-- >    }===========>+-- >    }==={negate}>+-- >       \========>+-- >  |]++nd :: QuasiQuoter+nd = QuasiQuoter { +    quoteExp = \str -> case (parseNeedle str) of+        Left e -> error . presentNeedleError $ e+        Right n -> arrowQ n+  , quotePat = error "Needles cannot be patterns."+  , quoteDec = error "Needles cannot be declarations."+  , quoteType = error "Needles cannot be types."+  }++-- | Load a needle from a file.+--+-- > {-# LANGUAGE TemplateHaskell #-}+-- > +-- > exampleArrow :: Float -> Float+-- > exampleArrow = $(ndFile "example.nd")++ndFile :: FilePath -> ExpQ+ndFile fp = do+    str <- runIO $ readFile fp+    case (parseNeedle str) of+        Left e -> error . presentNeedleError $ e+        Right n -> arrowQ n++-- | Convert NeedleArrow to ExpQ++arrowQ :: NeedleArrow -> ExpQ+arrowQ arrow = do+    let is = inputs arrow+    iNameMap <- M.fromList <$> mapM (\(a,b) -> ((a,b),) <$> newName ("_" ++ show a ++ "_" ++ show b)) is++    let iNames = Pre.map snd $ M.toList iNameMap+        iName (Input a b) = iNameMap ! (a,b)++        f i@(Input a b) = return +            $ AppE (VarE $ mkName "arr") +            $ LamE [TupP $ Pre.map VarP iNames] (VarE (iName i))++        f (Through a t) = do+            let ea = either error id $ parseExp . T.unpack $ t+            b <- f a+            return $ InfixE (Just b) (VarE $ mkName ">>>") (Just ea)++        f (Join as) = do+            aNames <- mapM (\n -> newName ("_" ++ show n)) [0..(Pre.length as - 1)]+            +            let tupleArrows [c] = f c+                tupleArrows (c:cs) = [| $(f c) &&& $(tupleArrows cs) |]++                tupleNames [n] = VarP n+                tupleNames (n:ns) = TupP [VarP n, tupleNames ns]++            b <- tupleArrows as++            return $ InfixE (Just b) (VarE $ mkName ">>>") $ Just+                $ AppE (VarE $ mkName "arr") +                $ LamE [tupleNames aNames] (TupE $ Pre.map VarE aNames)++    f arrow++inputs :: NeedleArrow -> [(Int, Int)]+inputs (Input a b) = [(a,b)]+inputs (Through a _) = inputs a+inputs (Join as) = as >>= inputs
+ LICENSE view
@@ -0,0 +1,20 @@+Copyright (c) 2014 Josh Kirklin++Permission is hereby granted, free of charge, to any person obtaining+a copy of this software and associated documentation files (the+"Software"), to deal in the Software without restriction, including+without limitation the rights to use, copy, modify, merge, publish,+distribute, sublicense, and/or sell copies of the Software, and to+permit persons to whom the Software is furnished to do so, subject to+the following conditions:++The above copyright notice and this permission notice shall be included+in all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ needle.cabal view
@@ -0,0 +1,34 @@+name:                needle+version:             0.1.0.0+synopsis:            ASCII-fied arrow notation+description:         Needle is a domain specific language for ASCII-fied arrow notation. See "Control.Arrow.Needle" for more information and an example.+license:             MIT+license-file:        LICENSE+author:              Josh Kirklin+maintainer:          Josh Kirklin <jjvk2@cam.ac.uk>+copyright:           (c) 2014 Josh Kirklin+category:            Control+build-type:          Simple+stability:           experimental+bug-reports:         https://github.com/ScrambledEggsOnToast/needle/issues+cabal-version:       >=1.10++library+  exposed-modules:     Control.Arrow.Needle+                       Control.Arrow.Needle.Parse+                       Control.Arrow.Needle.TH+  other-modules:       Control.Arrow.Needle.Internal.UnevenGrid+  build-depends:       base >=4.7 && <4.8+                     , text >=1.2 && <1.3+                     , parsec >= 3.1 && <3.2+                     , parsec-extra >=0.1 && <0.2+                     , containers >=0.5 && <0.6+                     , mtl >=2.2 && <2.3+                     , template-haskell+                     , haskell-src-meta >=0.6 && <0.7+                     , vector >= 0.10 && <0.11+  default-language:    Haskell2010++source-repository head+  type:     git+  location: git://github.com/ScrambledEggsOnToast/needle.git