module interactiveProgramsAgdaUnsized where
open import NativeIO
open import Function
record IOInterface : Set₁ where
field Command : Set
Response : (c : Command) → Set
open IOInterface public
mutual
record IO (I : IOInterface) (A : Set) : Set where
coinductive
constructor delay
field force : IO' I A
data IO' (I : IOInterface) (A : Set) : Set where
do' : (c : Command I) (f : Response I c → IO I A) → IO' I A
return' : (a : A) → IO' I A
open IO public
module _ {I : IOInterface} (let C = Command I) (let R = Response I) where
do : ∀{A} (c : C) (f : R c → IO I A) → IO I A
force (do c f) = do' c f
return : ∀{A} (a : A) → IO I A
force (return a) = return' a
infixl 2 _>>=_
_>>=_ : ∀{A B} (m : IO I A) (k : A → IO I B) → IO I B
force (m >>= k) with force m
... | do' c f = do' c λ x → f x >>= k
... | return' a = force (k a)
{-# NON_TERMINATING #-}
translateIO : ∀ {A} (tr : (c : C) → NativeIO (R c)) → IO I A → NativeIO A
translateIO tr m = case (force m) of λ
{ (do' c f) → (tr c) native>>= λ r → translateIO tr (f r)
; (return' a) → nativeReturn a
}
data ConsoleCommand : Set where
getLine : ConsoleCommand
putStrLn : String → ConsoleCommand
ConsoleResponse : ConsoleCommand → Set
ConsoleResponse getLine = String
ConsoleResponse (putStrLn s) = Unit
ConsoleInterface : IOInterface
Command ConsoleInterface = ConsoleCommand
Response ConsoleInterface = ConsoleResponse
IOConsole : Set → Set
IOConsole = IO ConsoleInterface
translateIOConsoleLocal : (c : ConsoleCommand) → NativeIO (ConsoleResponse c)
translateIOConsoleLocal (putStrLn s) = nativePutStrLn s
translateIOConsoleLocal getLine = nativeGetLine
translateIOConsole : {A : Set} → IOConsole A → NativeIO A
translateIOConsole = translateIO translateIOConsoleLocal
{-# NON_TERMINATING #-}
cat : IOConsole Unit
force cat = do' getLine λ{ line →
do (putStrLn line) λ _ →
cat
}
mutual
cat' : IOConsole Unit
force cat' = do' getLine λ{ line →
cat'' line}
cat'' : String → IOConsole Unit
force (cat'' line) = do' (putStrLn line) λ _ →
cat'
main : NativeIO Unit
main = translateIOConsole cat