Standard IO

fble-0.5 (2025-07-13,fble-0.4-212-ga8f8ad0f)

In this tutorial we'll learn how to write command line programs that interact with the environment.

Until now we've been writing fble programs that use /Core/Stdio/StringO%.Run to output a string:

 String@ output = Str|'hello, world';
 /Core/Stdio/StringO%.Run(output);

The /Core/Stdio% library provides a more general interface for writing fble programs that allows you to access command line arguments, access standard input, output, and error streams, read and write files, read environment variables, and return an exit status.

The /Core/Stdio/IO%.Run function takes a Main@ function with the following type:

<<@>@>@ Main@ = <<@>@ M@>(Stdio@<M@>, Monad@<M@>, List@<String@>) { M@<Bool@>; };

Here is an example hello world program using this more general interface:

# A hello world program using the Stdio@ interface.
Main@ Main = <<@>@ M@>(Stdio@<M@> stdio, Monad@<M@> m, List@<String@> _args) {
  % O = /Core/Stream/OStream%(m);
  
  Unit@ _ <- m.do(O.PutLine(stdio.out, Str|'hello, world'));
  m.return(True);
};

/Core/Stdio/IO%.Run(Main);

Let's break this down

<<@>@ M@>

The Main@ function is polymorphic, parameterized by type M@. The first two arguments to the function are stdio and m, which are interfaces supported by the abstract type M@.

This says your main function can be used with any type M@ that implements the Stdio@ and Monad@ interfaces. The /Core/Stdio/IO%.Run function provides a concrete type of M@ for use with the fble-stdio program.

The reason Main@ is polymorphic instead of hard coding the concrete type for M@ provided by /Core/Stdio/IO%.Run is to make your main function more general than just for use with fble-stdio. For example, you can write test cases for your main function using a simulated environment.

Stdio@<M@> stdio

The Stdio@<M@> interface is defined as follows:

<<@>@>@ Stdio@ = <<@>@ M@> { *(
  # stdin stream
  IStream@<M@> in,

  # stdout stream
  OStream@<M@> out,

  # stderr stream
  OStream@<M@> err,

  # Open the named file for reading.
  # Returns an input stream for reading. Nothing if unable to open the file.
  (String@) { M@<Maybe@<IStream@<M@>>>; } read,

  # Open the named file for writing.
  # Returns an output stream for writing. Nothing if unable to open the file.
  (String@) { M@<Maybe@<OStream@<M@>>>; } write,

  # Gets an environment variable value.
  (String@) { M@<Maybe@<String@>>; } getenv
); };

The IStream@ and OStream@ are types for reading a sequence of bytes. The Stdio@ interface represents bytes using the Int@ type:

<<@>@>@ IStream@ = <<@>@ M@> { M@<Maybe@<Int@>>; };
<<@>@>@ OStream@ = <<@>@ M@>(Int@) { M@<Unit@>; };

The fields in, out, and err let you read and write standard input and output streams.

The fields read and write let you open files for reading and writing respectively.

The field getenv lets you access the value of an environment variable.

Monad@<M@> m

The Monad@<M@> interface m provides a way to sequence operations. This is needed to have a well defined order of operations when interacting with input and output streams and files.

List@<String@> args

The args argument is the list of command line arguments passed when invoking the program. For example, if you ran your program as:

fble-stdio -p core -I . -m /Foo% -- hello there now

Then the value of args would be:

List[Str|'hello', Str|'there', Str|'now']

M@<Bool@>;

The result of the Main@ program has type M@<Bool@>. If you return True using m.return(True), your program will have exit status 0. Otherwise your program will have exit status 1.

Exercises

Write an fble program that prints out a sorted list of the command line arguments passed to it.

Write an fble program that outputs the length of a given file. Try passing the file via standard input and as a file path.

Write an fble program that repeatedly prompts the user for a number and outputs the largest number input so far.

Next Steps

This completes this tutorial series on the fble language. You now understand all the fble language features and can write interesting programs that interact with the environment on the command line. Go forth now and program.

Or you can head back to the Tutorials page for links to debug and profiling guides.