packages feed

GenZ-0.1.0.0: lib/Basics.hs

module Basics where

import Data.GraphViz
import Data.GraphViz.Types.Monadic hiding ((-->))
import GHC.IO.Handle
import System.IO
import System.IO.Temp
import System.IO.Unsafe
import qualified Data.ByteString as BS
import Data.Either
import Data.List (filter)
import Data.Set
import qualified Data.Set as Set

-- | Displayable things, using graphviz.
class DispAble t where
  toGraph :: t -> DotM String ()
  disp :: t -> IO ()
  disp x = runGraphvizCanvas Dot (digraph' $ toGraph x) Xlib
  dot :: t -> IO ()
  dot x = graphvizWithHandle Dot (digraph' $ toGraph x) Canon $ \h -> do
    hSetEncoding h utf8
    BS.hGetContents h >>= BS.putStr
  svg :: t -> String
  svg x = unsafePerformIO $ withSystemTempDirectory "tapdleau" $ \tmpdir -> do
    _ <- runGraphvizCommand Dot (digraph' $ toGraph x) Svg (tmpdir ++ "/temp.svg")
    readFile (tmpdir ++ "/temp.svg")
  pdf :: t -> IO FilePath
  pdf x = runGraphvizCommand Dot (digraph' $ toGraph x) Pdf "temp.pdf"

-- | Zipper for trees
class TreeLike z where
  zsingleton :: a -> z a
  move_left :: z a -> z a
  move_right :: z a -> z a
  move_up :: z a-> z a
  move_down :: z a -> z a
  zdelete :: z a -> z a

-- | Pick one element of each list to form new lists.
pickOneOfEach :: [[a]] -> [[a]]
pickOneOfEach [] = [[]]
pickOneOfEach (l:ls) = [ x:xs | x <- l, xs <- pickOneOfEach ls ]

-- | Filter if any element has the propery, otherwise keep all.
filterIfAny :: (a -> Bool) -> [a] -> [a]
filterIfAny f xs = if any f xs then Data.List.filter f xs else xs

-- | Same as @filterIfAny@ but only traversing the list once.
filterIfAny' :: (a -> Bool) -> [a] -> [a]
filterIfAny' f xs = loop xs where
  loop []     = []
  loop [y]    = if f y then [y] else xs -- return original list
  loop (y:ys) = if f y then y : Data.List.filter f ys else loop ys

-- | Helper functions for Set & Either
fromEither :: Either a a -> a
fromEither (Left x) = x
fromEither (Right x) = x

leftsSet :: Ord a => Set (Either a a) -> Set a
leftsSet xs = Set.map fromEither $ Set.filter isLeft xs

rightsSet :: Ord a => Set (Either a a) -> Set a
rightsSet xs = Set.map fromEither $ Set.filter isRight xs

leftOfSet :: Ord a => Set (Either a a) -> Set (Either a a)
leftOfSet = Set.filter isLeft

rightOfSet :: Ord a => Set (Either a a) -> Set (Either a a)
rightOfSet = Set.filter isRight

-- | Define another set by providing a filter and a map function.
setComprehension :: (Ord a, Ord b) => (a -> Bool) -> (a -> b) -> Set a -> Set b
setComprehension f g xs = Set.map g (Set.filter f xs)