packages feed

polysemy-scoped-fs-0.1.0.0: src/Polysemy/SequentialAccess.hs

{-|
Copyright   : (c) Hisaket VioletRed, 2022
License     : AGPL-3.0-or-later
Maintainer  : hisaket@outlook.jp
Stability   : experimental
Portability : POSIX
-}

module Polysemy.SequentialAccess where

import Polysemy ( Member, Sem, interpret, makeSem )
import Prelude hiding ( Read, read )
import Polysemy.Input ( Input (Input) )
import Polysemy.Output ( Output (Output) )


data GetPosition pos m a where
    GetPosition :: GetPosition pos m pos
{- ^An effect that gets the current cursor position in the file.
-}
makeSem ''GetPosition

{- |A type that represents both ends or intermediate positions in the file.
-}
data TriPosition = End Ends | Intermediate
    deriving (Eq, Ord, Show)

{- |A type that represents both ends of the file.
-}
data Ends =
      TOF -- ^Top of file
    | EOF -- ^End of file
    deriving (Eq, Ord, Show)


data Seek pos m a where
    Seek :: pos -> Seek pos m ()
{- ^An effect that moves the cursor.
-}
makeSem ''Seek

{- |A wrapper type that represents an absolute position in the file.
-}
newtype Absolute a = Absolute a deriving (Eq, Ord, Show)

{- |A wrapper type that represents relative position from the current cursor position.
-}
newtype Relative a = Relative a deriving (Eq, Ord, Show)

{- |A wrapper type that represents relative position from the end of the file.
-}
newtype FromEnd a = FromEnd a deriving (Eq, Ord, Show)


data Read sz i m a where
   Read :: sz -> Read sz i m i
{- ^An effect that gets file contents by the size 'sz' from the current
   position.
-}
makeSem ''Read

{- |An effect that gets file contents from current position to the end of the
   file.
-}
type ReadToEnd = Read ToEnd

{- |A singleton that represents the size from the current position to the end of
   the file.
-}
data ToEnd = ToEnd deriving (Eq, Ord, Show)

-- |A singleton that represents the size 0.
data NullSize = NullSize deriving (Eq, Ord, Show)

{- |Transforms an 'Input' effect into an 'Read' effect with the fixed size.
-}
inputToRead :: Member (Read sz i) r => sz -> Sem (Input i ': r) a -> Sem r a
inputToRead sz = interpret \Input -> read sz


data Overwrite o m a where
    Overwrite :: o -> Overwrite o m ()
{- ^An effect that overwrites file contents by the data 'o' from current
   position.
-}
makeSem ''Overwrite

{- |Transforms an 'Output' effect into an `Overwrite` effect.
-}
outputToOverwrite :: Member (Overwrite o) r => Sem (Output o ': r) a -> Sem r a
outputToOverwrite = interpret \(Output o) -> overwrite o


data Extend o m a where
    Extend :: o -> Extend o m ()
-- ^An effect that extends a file by the data 'o' from the end of a file.
-- The cursor is not moved.
makeSem ''Extend

data Append o m a where
    Append :: o -> Append o m ()
-- ^An effect that extends a file by the data 'o' from the end of a file.
-- The cursor is moved to the end of the file after extending.
makeSem ''Append

{- |Transforms an 'Output' effect into an `Extend` effect.
-}
outputToExtend :: Member (Extend o) r => Sem (Output o ': r) a -> Sem r a
outputToExtend = interpret \(Output o) -> extend o

-- |Transforms an 'Output' effect into an `Append` effect.
outputToAppend :: Member (Append o) r => Sem (Output o ': r) a -> Sem r a
outputToAppend = interpret \(Output o) -> append o


data Resize sz m a where
    Resize :: sz -> Resize sz m ()
{- ^An effect that resizes a file by the size 'sz'.
   
   Note: The initial data in space made by a growing is interpreter-dependent.
-}
makeSem ''Resize