{-|
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 (TriPosition -> TriPosition -> Bool
(TriPosition -> TriPosition -> Bool)
-> (TriPosition -> TriPosition -> Bool) -> Eq TriPosition
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: TriPosition -> TriPosition -> Bool
$c/= :: TriPosition -> TriPosition -> Bool
== :: TriPosition -> TriPosition -> Bool
$c== :: TriPosition -> TriPosition -> Bool
Eq, Eq TriPosition
Eq TriPosition
-> (TriPosition -> TriPosition -> Ordering)
-> (TriPosition -> TriPosition -> Bool)
-> (TriPosition -> TriPosition -> Bool)
-> (TriPosition -> TriPosition -> Bool)
-> (TriPosition -> TriPosition -> Bool)
-> (TriPosition -> TriPosition -> TriPosition)
-> (TriPosition -> TriPosition -> TriPosition)
-> Ord TriPosition
TriPosition -> TriPosition -> Bool
TriPosition -> TriPosition -> Ordering
TriPosition -> TriPosition -> TriPosition
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: TriPosition -> TriPosition -> TriPosition
$cmin :: TriPosition -> TriPosition -> TriPosition
max :: TriPosition -> TriPosition -> TriPosition
$cmax :: TriPosition -> TriPosition -> TriPosition
>= :: TriPosition -> TriPosition -> Bool
$c>= :: TriPosition -> TriPosition -> Bool
> :: TriPosition -> TriPosition -> Bool
$c> :: TriPosition -> TriPosition -> Bool
<= :: TriPosition -> TriPosition -> Bool
$c<= :: TriPosition -> TriPosition -> Bool
< :: TriPosition -> TriPosition -> Bool
$c< :: TriPosition -> TriPosition -> Bool
compare :: TriPosition -> TriPosition -> Ordering
$ccompare :: TriPosition -> TriPosition -> Ordering
$cp1Ord :: Eq TriPosition
Ord, Int -> TriPosition -> ShowS
[TriPosition] -> ShowS
TriPosition -> String
(Int -> TriPosition -> ShowS)
-> (TriPosition -> String)
-> ([TriPosition] -> ShowS)
-> Show TriPosition
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [TriPosition] -> ShowS
$cshowList :: [TriPosition] -> ShowS
show :: TriPosition -> String
$cshow :: TriPosition -> String
showsPrec :: Int -> TriPosition -> ShowS
$cshowsPrec :: Int -> TriPosition -> ShowS
Show)

{- |A type that represents both ends of the file.
-}
data Ends =
      TOF -- ^Top of file
    | EOF -- ^End of file
    deriving (Ends -> Ends -> Bool
(Ends -> Ends -> Bool) -> (Ends -> Ends -> Bool) -> Eq Ends
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Ends -> Ends -> Bool
$c/= :: Ends -> Ends -> Bool
== :: Ends -> Ends -> Bool
$c== :: Ends -> Ends -> Bool
Eq, Eq Ends
Eq Ends
-> (Ends -> Ends -> Ordering)
-> (Ends -> Ends -> Bool)
-> (Ends -> Ends -> Bool)
-> (Ends -> Ends -> Bool)
-> (Ends -> Ends -> Bool)
-> (Ends -> Ends -> Ends)
-> (Ends -> Ends -> Ends)
-> Ord Ends
Ends -> Ends -> Bool
Ends -> Ends -> Ordering
Ends -> Ends -> Ends
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Ends -> Ends -> Ends
$cmin :: Ends -> Ends -> Ends
max :: Ends -> Ends -> Ends
$cmax :: Ends -> Ends -> Ends
>= :: Ends -> Ends -> Bool
$c>= :: Ends -> Ends -> Bool
> :: Ends -> Ends -> Bool
$c> :: Ends -> Ends -> Bool
<= :: Ends -> Ends -> Bool
$c<= :: Ends -> Ends -> Bool
< :: Ends -> Ends -> Bool
$c< :: Ends -> Ends -> Bool
compare :: Ends -> Ends -> Ordering
$ccompare :: Ends -> Ends -> Ordering
$cp1Ord :: Eq Ends
Ord, Int -> Ends -> ShowS
[Ends] -> ShowS
Ends -> String
(Int -> Ends -> ShowS)
-> (Ends -> String) -> ([Ends] -> ShowS) -> Show Ends
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Ends] -> ShowS
$cshowList :: [Ends] -> ShowS
show :: Ends -> String
$cshow :: Ends -> String
showsPrec :: Int -> Ends -> ShowS
$cshowsPrec :: Int -> Ends -> ShowS
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 (Absolute a -> Absolute a -> Bool
(Absolute a -> Absolute a -> Bool)
-> (Absolute a -> Absolute a -> Bool) -> Eq (Absolute a)
forall a. Eq a => Absolute a -> Absolute a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Absolute a -> Absolute a -> Bool
$c/= :: forall a. Eq a => Absolute a -> Absolute a -> Bool
== :: Absolute a -> Absolute a -> Bool
$c== :: forall a. Eq a => Absolute a -> Absolute a -> Bool
Eq, Eq (Absolute a)
Eq (Absolute a)
-> (Absolute a -> Absolute a -> Ordering)
-> (Absolute a -> Absolute a -> Bool)
-> (Absolute a -> Absolute a -> Bool)
-> (Absolute a -> Absolute a -> Bool)
-> (Absolute a -> Absolute a -> Bool)
-> (Absolute a -> Absolute a -> Absolute a)
-> (Absolute a -> Absolute a -> Absolute a)
-> Ord (Absolute a)
Absolute a -> Absolute a -> Bool
Absolute a -> Absolute a -> Ordering
Absolute a -> Absolute a -> Absolute a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Absolute a)
forall a. Ord a => Absolute a -> Absolute a -> Bool
forall a. Ord a => Absolute a -> Absolute a -> Ordering
forall a. Ord a => Absolute a -> Absolute a -> Absolute a
min :: Absolute a -> Absolute a -> Absolute a
$cmin :: forall a. Ord a => Absolute a -> Absolute a -> Absolute a
max :: Absolute a -> Absolute a -> Absolute a
$cmax :: forall a. Ord a => Absolute a -> Absolute a -> Absolute a
>= :: Absolute a -> Absolute a -> Bool
$c>= :: forall a. Ord a => Absolute a -> Absolute a -> Bool
> :: Absolute a -> Absolute a -> Bool
$c> :: forall a. Ord a => Absolute a -> Absolute a -> Bool
<= :: Absolute a -> Absolute a -> Bool
$c<= :: forall a. Ord a => Absolute a -> Absolute a -> Bool
< :: Absolute a -> Absolute a -> Bool
$c< :: forall a. Ord a => Absolute a -> Absolute a -> Bool
compare :: Absolute a -> Absolute a -> Ordering
$ccompare :: forall a. Ord a => Absolute a -> Absolute a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Absolute a)
Ord, Int -> Absolute a -> ShowS
[Absolute a] -> ShowS
Absolute a -> String
(Int -> Absolute a -> ShowS)
-> (Absolute a -> String)
-> ([Absolute a] -> ShowS)
-> Show (Absolute a)
forall a. Show a => Int -> Absolute a -> ShowS
forall a. Show a => [Absolute a] -> ShowS
forall a. Show a => Absolute a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Absolute a] -> ShowS
$cshowList :: forall a. Show a => [Absolute a] -> ShowS
show :: Absolute a -> String
$cshow :: forall a. Show a => Absolute a -> String
showsPrec :: Int -> Absolute a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Absolute a -> ShowS
Show)

{- |A wrapper type that represents relative position from the current cursor position.
-}
newtype Relative a = Relative a deriving (Relative a -> Relative a -> Bool
(Relative a -> Relative a -> Bool)
-> (Relative a -> Relative a -> Bool) -> Eq (Relative a)
forall a. Eq a => Relative a -> Relative a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Relative a -> Relative a -> Bool
$c/= :: forall a. Eq a => Relative a -> Relative a -> Bool
== :: Relative a -> Relative a -> Bool
$c== :: forall a. Eq a => Relative a -> Relative a -> Bool
Eq, Eq (Relative a)
Eq (Relative a)
-> (Relative a -> Relative a -> Ordering)
-> (Relative a -> Relative a -> Bool)
-> (Relative a -> Relative a -> Bool)
-> (Relative a -> Relative a -> Bool)
-> (Relative a -> Relative a -> Bool)
-> (Relative a -> Relative a -> Relative a)
-> (Relative a -> Relative a -> Relative a)
-> Ord (Relative a)
Relative a -> Relative a -> Bool
Relative a -> Relative a -> Ordering
Relative a -> Relative a -> Relative a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Relative a)
forall a. Ord a => Relative a -> Relative a -> Bool
forall a. Ord a => Relative a -> Relative a -> Ordering
forall a. Ord a => Relative a -> Relative a -> Relative a
min :: Relative a -> Relative a -> Relative a
$cmin :: forall a. Ord a => Relative a -> Relative a -> Relative a
max :: Relative a -> Relative a -> Relative a
$cmax :: forall a. Ord a => Relative a -> Relative a -> Relative a
>= :: Relative a -> Relative a -> Bool
$c>= :: forall a. Ord a => Relative a -> Relative a -> Bool
> :: Relative a -> Relative a -> Bool
$c> :: forall a. Ord a => Relative a -> Relative a -> Bool
<= :: Relative a -> Relative a -> Bool
$c<= :: forall a. Ord a => Relative a -> Relative a -> Bool
< :: Relative a -> Relative a -> Bool
$c< :: forall a. Ord a => Relative a -> Relative a -> Bool
compare :: Relative a -> Relative a -> Ordering
$ccompare :: forall a. Ord a => Relative a -> Relative a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Relative a)
Ord, Int -> Relative a -> ShowS
[Relative a] -> ShowS
Relative a -> String
(Int -> Relative a -> ShowS)
-> (Relative a -> String)
-> ([Relative a] -> ShowS)
-> Show (Relative a)
forall a. Show a => Int -> Relative a -> ShowS
forall a. Show a => [Relative a] -> ShowS
forall a. Show a => Relative a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Relative a] -> ShowS
$cshowList :: forall a. Show a => [Relative a] -> ShowS
show :: Relative a -> String
$cshow :: forall a. Show a => Relative a -> String
showsPrec :: Int -> Relative a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Relative a -> ShowS
Show)

{- |A wrapper type that represents relative position from the end of the file.
-}
newtype FromEnd a = FromEnd a deriving (FromEnd a -> FromEnd a -> Bool
(FromEnd a -> FromEnd a -> Bool)
-> (FromEnd a -> FromEnd a -> Bool) -> Eq (FromEnd a)
forall a. Eq a => FromEnd a -> FromEnd a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FromEnd a -> FromEnd a -> Bool
$c/= :: forall a. Eq a => FromEnd a -> FromEnd a -> Bool
== :: FromEnd a -> FromEnd a -> Bool
$c== :: forall a. Eq a => FromEnd a -> FromEnd a -> Bool
Eq, Eq (FromEnd a)
Eq (FromEnd a)
-> (FromEnd a -> FromEnd a -> Ordering)
-> (FromEnd a -> FromEnd a -> Bool)
-> (FromEnd a -> FromEnd a -> Bool)
-> (FromEnd a -> FromEnd a -> Bool)
-> (FromEnd a -> FromEnd a -> Bool)
-> (FromEnd a -> FromEnd a -> FromEnd a)
-> (FromEnd a -> FromEnd a -> FromEnd a)
-> Ord (FromEnd a)
FromEnd a -> FromEnd a -> Bool
FromEnd a -> FromEnd a -> Ordering
FromEnd a -> FromEnd a -> FromEnd a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (FromEnd a)
forall a. Ord a => FromEnd a -> FromEnd a -> Bool
forall a. Ord a => FromEnd a -> FromEnd a -> Ordering
forall a. Ord a => FromEnd a -> FromEnd a -> FromEnd a
min :: FromEnd a -> FromEnd a -> FromEnd a
$cmin :: forall a. Ord a => FromEnd a -> FromEnd a -> FromEnd a
max :: FromEnd a -> FromEnd a -> FromEnd a
$cmax :: forall a. Ord a => FromEnd a -> FromEnd a -> FromEnd a
>= :: FromEnd a -> FromEnd a -> Bool
$c>= :: forall a. Ord a => FromEnd a -> FromEnd a -> Bool
> :: FromEnd a -> FromEnd a -> Bool
$c> :: forall a. Ord a => FromEnd a -> FromEnd a -> Bool
<= :: FromEnd a -> FromEnd a -> Bool
$c<= :: forall a. Ord a => FromEnd a -> FromEnd a -> Bool
< :: FromEnd a -> FromEnd a -> Bool
$c< :: forall a. Ord a => FromEnd a -> FromEnd a -> Bool
compare :: FromEnd a -> FromEnd a -> Ordering
$ccompare :: forall a. Ord a => FromEnd a -> FromEnd a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (FromEnd a)
Ord, Int -> FromEnd a -> ShowS
[FromEnd a] -> ShowS
FromEnd a -> String
(Int -> FromEnd a -> ShowS)
-> (FromEnd a -> String)
-> ([FromEnd a] -> ShowS)
-> Show (FromEnd a)
forall a. Show a => Int -> FromEnd a -> ShowS
forall a. Show a => [FromEnd a] -> ShowS
forall a. Show a => FromEnd a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FromEnd a] -> ShowS
$cshowList :: forall a. Show a => [FromEnd a] -> ShowS
show :: FromEnd a -> String
$cshow :: forall a. Show a => FromEnd a -> String
showsPrec :: Int -> FromEnd a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> FromEnd a -> ShowS
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 (ToEnd -> ToEnd -> Bool
(ToEnd -> ToEnd -> Bool) -> (ToEnd -> ToEnd -> Bool) -> Eq ToEnd
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ToEnd -> ToEnd -> Bool
$c/= :: ToEnd -> ToEnd -> Bool
== :: ToEnd -> ToEnd -> Bool
$c== :: ToEnd -> ToEnd -> Bool
Eq, Eq ToEnd
Eq ToEnd
-> (ToEnd -> ToEnd -> Ordering)
-> (ToEnd -> ToEnd -> Bool)
-> (ToEnd -> ToEnd -> Bool)
-> (ToEnd -> ToEnd -> Bool)
-> (ToEnd -> ToEnd -> Bool)
-> (ToEnd -> ToEnd -> ToEnd)
-> (ToEnd -> ToEnd -> ToEnd)
-> Ord ToEnd
ToEnd -> ToEnd -> Bool
ToEnd -> ToEnd -> Ordering
ToEnd -> ToEnd -> ToEnd
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: ToEnd -> ToEnd -> ToEnd
$cmin :: ToEnd -> ToEnd -> ToEnd
max :: ToEnd -> ToEnd -> ToEnd
$cmax :: ToEnd -> ToEnd -> ToEnd
>= :: ToEnd -> ToEnd -> Bool
$c>= :: ToEnd -> ToEnd -> Bool
> :: ToEnd -> ToEnd -> Bool
$c> :: ToEnd -> ToEnd -> Bool
<= :: ToEnd -> ToEnd -> Bool
$c<= :: ToEnd -> ToEnd -> Bool
< :: ToEnd -> ToEnd -> Bool
$c< :: ToEnd -> ToEnd -> Bool
compare :: ToEnd -> ToEnd -> Ordering
$ccompare :: ToEnd -> ToEnd -> Ordering
$cp1Ord :: Eq ToEnd
Ord, Int -> ToEnd -> ShowS
[ToEnd] -> ShowS
ToEnd -> String
(Int -> ToEnd -> ShowS)
-> (ToEnd -> String) -> ([ToEnd] -> ShowS) -> Show ToEnd
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ToEnd] -> ShowS
$cshowList :: [ToEnd] -> ShowS
show :: ToEnd -> String
$cshow :: ToEnd -> String
showsPrec :: Int -> ToEnd -> ShowS
$cshowsPrec :: Int -> ToEnd -> ShowS
Show)

-- |A singleton that represents the size 0.
data NullSize = NullSize deriving (NullSize -> NullSize -> Bool
(NullSize -> NullSize -> Bool)
-> (NullSize -> NullSize -> Bool) -> Eq NullSize
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NullSize -> NullSize -> Bool
$c/= :: NullSize -> NullSize -> Bool
== :: NullSize -> NullSize -> Bool
$c== :: NullSize -> NullSize -> Bool
Eq, Eq NullSize
Eq NullSize
-> (NullSize -> NullSize -> Ordering)
-> (NullSize -> NullSize -> Bool)
-> (NullSize -> NullSize -> Bool)
-> (NullSize -> NullSize -> Bool)
-> (NullSize -> NullSize -> Bool)
-> (NullSize -> NullSize -> NullSize)
-> (NullSize -> NullSize -> NullSize)
-> Ord NullSize
NullSize -> NullSize -> Bool
NullSize -> NullSize -> Ordering
NullSize -> NullSize -> NullSize
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: NullSize -> NullSize -> NullSize
$cmin :: NullSize -> NullSize -> NullSize
max :: NullSize -> NullSize -> NullSize
$cmax :: NullSize -> NullSize -> NullSize
>= :: NullSize -> NullSize -> Bool
$c>= :: NullSize -> NullSize -> Bool
> :: NullSize -> NullSize -> Bool
$c> :: NullSize -> NullSize -> Bool
<= :: NullSize -> NullSize -> Bool
$c<= :: NullSize -> NullSize -> Bool
< :: NullSize -> NullSize -> Bool
$c< :: NullSize -> NullSize -> Bool
compare :: NullSize -> NullSize -> Ordering
$ccompare :: NullSize -> NullSize -> Ordering
$cp1Ord :: Eq NullSize
Ord, Int -> NullSize -> ShowS
[NullSize] -> ShowS
NullSize -> String
(Int -> NullSize -> ShowS)
-> (NullSize -> String) -> ([NullSize] -> ShowS) -> Show NullSize
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NullSize] -> ShowS
$cshowList :: [NullSize] -> ShowS
show :: NullSize -> String
$cshow :: NullSize -> String
showsPrec :: Int -> NullSize -> ShowS
$cshowsPrec :: Int -> NullSize -> ShowS
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 -> Sem (Input i : r) a -> Sem r a
inputToRead sz
sz = (forall (rInitial :: EffectRow) x.
 Input i (Sem rInitial) x -> Sem r x)
-> Sem (Input i : r) a -> Sem r a
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
FirstOrder e "interpret" =>
(forall (rInitial :: EffectRow) x. e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret \Input i (Sem rInitial) x
Input -> sz -> Sem r x
forall sz i (r :: EffectRow). Member (Read sz i) r => sz -> Sem r i
read sz
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 :: Sem (Output o : r) a -> Sem r a
outputToOverwrite = (forall (rInitial :: EffectRow) x.
 Output o (Sem rInitial) x -> Sem r x)
-> Sem (Output o : r) a -> Sem r a
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
FirstOrder e "interpret" =>
(forall (rInitial :: EffectRow) x. e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret \(Output o) -> o -> Sem r ()
forall o (r :: EffectRow). Member (Overwrite o) r => o -> Sem r ()
overwrite o
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 :: Sem (Output o : r) a -> Sem r a
outputToExtend = (forall (rInitial :: EffectRow) x.
 Output o (Sem rInitial) x -> Sem r x)
-> Sem (Output o : r) a -> Sem r a
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
FirstOrder e "interpret" =>
(forall (rInitial :: EffectRow) x. e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret \(Output o) -> o -> Sem r ()
forall o (r :: EffectRow). Member (Extend o) r => o -> Sem r ()
extend o
o

-- |Transforms an 'Output' effect into an `Append` effect.
outputToAppend :: Member (Append o) r => Sem (Output o ': r) a -> Sem r a
outputToAppend :: Sem (Output o : r) a -> Sem r a
outputToAppend = (forall (rInitial :: EffectRow) x.
 Output o (Sem rInitial) x -> Sem r x)
-> Sem (Output o : r) a -> Sem r a
forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
FirstOrder e "interpret" =>
(forall (rInitial :: EffectRow) x. e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret \(Output o) -> o -> Sem r ()
forall o (r :: EffectRow). Member (Append o) r => o -> Sem r ()
append o
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