module System.Chatty.Filesystem where
import Control.Monad
import Control.Monad.State
import Control.Monad.Identity
import Data.Chatty.Atoms
import Text.Chatty.Printer
import Text.Chatty.Scanner
data FSExec a = FSSucc a
| NoPermission
| NotFound
data File m = File {
loadFun :: m (FSExec ()),
saveFun :: m (FSExec ()),
closeFun :: m (),
leftBehind :: String,
rightPending :: String
}
type FileA m = Atom (File m)
class ChAtoms m => ChFilesystem m where
fopen :: String -> m (FSExec (FileA m))
class Monad m => CanLoad m n where
fload :: FileA n -> m (FSExec ())
class Monad m => CanSave m n where
fsave :: FileA n -> m (FSExec ())
data FilePrinterT m a = FilePrinter { runFilePrinterT :: FileA m -> m a }
data FileScannerT m a = FileScanner { runFileScannerT :: FileA m -> m a }
instance Monad m => Monad (FilePrinterT m) where
return a = FilePrinter $ \_ -> return a
m >>= f = FilePrinter $ \d -> do a <- runFilePrinterT m d; runFilePrinterT (f a) d
instance Monad m => Monad (FileScannerT m) where
return a = FileScanner $ \_ -> return a
m >>= f = FileScanner $ \d -> do a <- runFileScannerT m d; runFileScannerT (f a) d
instance Functor f => Functor (FilePrinterT f) where
fmap f a = FilePrinter $ fmap f . runFilePrinterT a
instance Functor f => Functor (FileScannerT f) where
fmap f a = FileScanner $ fmap f . runFileScannerT a
instance MonadTrans FilePrinterT where
lift m = FilePrinter $ \_ -> m
instance MonadTrans FileScannerT where
lift m = FileScanner $ \_ -> m
instance MonadIO m => MonadIO (FilePrinterT m) where
liftIO = lift . liftIO
instance MonadIO m => MonadIO (FileScannerT m) where
liftIO = lift . liftIO
instance ChAtoms m => ChPrinter (FilePrinterT m) where
mprint s = FilePrinter $ \d -> do
f <- getAtom d
putAtom d f{leftBehind=reverse (take (length s) $ rightPending f) ++ leftBehind f, rightPending=drop (length s) $ rightPending f}
instance ChAtoms m => ChScanner (FileScannerT m) where
mscan1 = FileScanner $ \d -> do
f <- getAtom d
putAtom d f{leftBehind=head (rightPending f) : leftBehind f, rightPending=tail $ rightPending f}
return $ head $ rightPending f
mscanL = FileScanner $ liftM rightPending . getAtom
mscannable = FileScanner $ liftM (not . null . rightPending) . getAtom
mready = mscannable