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