monopati-0.1.0: System/Monopati.hs
module System.Monopati (Path (..), Points (..), Reference (..)
, part, points, next, (<^>), (</>)) where
import "base" Data.Function ((.), ($))
import "base" Data.Maybe (Maybe (Just, Nothing))
import "base" Data.String (String)
import "base" Data.Semigroup ((<>))
import "base" Text.Show (Show (show))
import "comonad" Control.Comonad (extract)
import "free" Control.Comonad.Cofree (Cofree ((:<)))
type Stack = Cofree Maybe
-- | Relative paths defined in direct order, absolute - in reverse
data Reference = Absolute | Relative
-- | Path may points to a directory or a file
data Points = Directory | File
-- | These two phantom paramaters needs for static analysis
data Path (reference :: Reference) (points :: Points) = Path { path :: Stack String }
instance Show (Path Absolute points) where
show (Path (x :< Just xs)) = show (Path @Absolute xs) <> "/" <> x
show (Path (x :< Nothing)) = "/" <> x
instance Show (Path Relative points) where
show (Path (x :< Just xs)) = x <> "/" <> show (Path @Relative xs)
show (Path (x :< Nothing)) = x
-- | Immerse some string into a path component
part :: String -> Path referece points
part x = Path $ x :< Nothing
points :: Path Absolute points -> String
points = extract . path
next :: Path Relative points -> String
next = extract . path
-- | Concatenate Relative and Relative paths
(<^>) :: Path Relative Directory -> Path Relative points -> Path Relative points
Path (x :< Nothing) <^> Path that = Path $ x :< Just that
Path (x :< Just this) <^> Path that = part x <^> (Path this <^> Path that)
-- | Concatenate Absolute and Relative paths
(</>) :: Path Absolute Directory -> Path Relative points -> Path Absolute points
Path absolute </> Path (x :< Nothing) = Path . (:<) x . Just $ absolute
Path absolute </> Path (x :< Just xs) = (Path . (:<) x . Just $ absolute) </> Path xs