Idris2/libs/base/System/REPL.idr
Edwin Brady dbdf7dab3d Back to HasIO, remove MonadIO
Following a fairly detailed discussion on slack, the feeling is
generally that it's better to have a single interface. While precision
is nice, it doesn't appear to buy us anything here. If that turns out to
be wrong, or limiting somehow, we can revisit it later. Also:

- it's easier for backend authors if the type of IO operations is
  slightly less restrictive. For example, if it's in HasIO, that limits
  alternative implementations, which might be awkward for some
  alternative back ends.
- it's one less extra detail to learn. This is minor, but there needs to
  be a clear advantage if there's more detail to learn.
- It is difficult to think of an underlying type that can't have a Monad
  instance (I have personally never encountered one - if they turns out
  to exist, again, we can revisit!)
2020-06-21 19:21:22 +01:00

38 lines
1.1 KiB
Idris

module System.REPL
import System.File
||| A basic read-eval-print loop, maintaining a state
||| @ state the input state
||| @ prompt the prompt to show
||| @ onInput the function to run on reading input, returning a String to
||| output and a new state. Returns Nothing if the repl should exit
export
replWith : HasIO io =>
(state : a) -> (prompt : String) ->
(onInput : a -> String -> Maybe (String, a)) -> io ()
replWith acc prompt fn
= do eof <- fEOF stdin
if eof
then pure ()
else do putStr prompt
fflush stdout
x <- getLine
case fn acc x of
Just (out, acc') =>
do putStr out
replWith acc' prompt fn
Nothing => pure ()
||| A basic read-eval-print loop
||| @ prompt the prompt to show
||| @ onInput the function to run on reading input, returning a String to
||| output
export
repl : HasIO io =>
(prompt : String) -> (onInput : String -> String) -> io ()
repl prompt fn
= replWith () prompt (\x, s => Just (fn s, ()))