Agda Programming Environment

Edit:

my agda-helper program is obsolete, given that “agda -I” works (though it might say that it’s not supported). :typeOf is equivalent to the :t in agda-helper.

the problems getting emacs’s agda-mode to work properly was due to a version mis-match between the Haskell Agda library and the Agda I installed with apt-get.

to fix everything, build Agda from source or find an up to date binary rather than using apt-get

Original Post

Agda is a dependently typed, functional programming language. It bears some syntactic resemblance to Haskell, though I am told that once I actually start using it, I’ll find this resemblance to only be skin deep. This post is not about the Agda programming language, but about the development environment one uses when programming in Agda. That is, it’s about the tools used to write, compile, check and test Agda code. More specifically, it’s about my experience setting up these tools on my computer. I’m posting this because the experience was somewhat tedious, and so knowledge of it may help others make their experiences less tedious. It also resulted in the development of a simple tool that might make some people’s lives easier when testing Agda programs, but more on that later.

Installing Agda

For the record, my box runs 64 bit Ubuntu 12.04. The first thing I did was:

% apt-get install agda

So far so good. Next, I installed the Agda libraries for Haskell. “Agda libraries for haskell?” you ask. Operations on Agda programs are done through a Haskell interface. For people new to Haskell, it has its own package manager called “cabal”.

% cabal install agda agda-executables

And cross your fingers. Cabal has always been very touch and go in my experience, but after re-installing ghc (the Haskell compiler) and deleting my “~/.cabal” directory several times the, gods of Haskell decided to grant me with a working install of the Agda-2.3.0.1 library (the version compatible with ghc7.4.1 which I happen to run). I know there was probably a more elegant way to install that, but meh - it worked. For people treating this as instructions for setting up Agda, I recommend you at least try to install the Haskell library without doing what I did.

Hello, World?

Not exactly. Once Agda was installed, I had a nice little “agda” binary that was, among other things, an Agda compiler. I wrote a little Agda program to make sure everything worked. It wasn’t the traditional first-program-in-language, that just prints out “Hello, World!”, because in Agda, like in most functional languages, the emphasis is on defining equations rather than doing things, and printing out a string is doing something so is actually non-trivial. Instead, I defined a simple type:

-- file: hello.agda
module hello where
data Blah : Set where
a : Blah

Without getting into too much detail, this code defines a type “Blah”, and a data constructor “a” that is a member of that type. It’s worth noting that this will not compile, since it lacks a “main” function (which is what the compiled program does when it’s run). But it took me a while for me to figure out how to get that information.

I’ll highlight my thought process. First I looked at the documentation that came with Agda:

That’s actually it. There is no man page for this program. The first bit of that that looked relevant is the “-c” option which compiles an Agda program. This was before I realized the necessity for a main function. So I ran:

$ agda -c hello.agda

The resulting error message explains that I need a main function. Good we’re getting somewhere.

Then I tried importing a standard library function into my agda program. I added this line to the start of the module:

open import Data.Char

and compiled:

[/home/steve/src/agda][steve@stevebox]$ agda -c test.agda [19:39:35]
Checking test(/home/steve/src/agda/test.agda).
/home/steve/src/agda/test.agda:3,1-22
Failed to find source of module Data.Char in any of the following
locations:
/home/steve/src/agda/Data/Char.agda
/home/steve/src/agda/Data/Char.lagda
when scope checking the declaration
open import Data.Char

Pretty easy to figure out what’s going on here. The compiler doesn’t know where to look for the standard library. I had a wild stab in the dark:

(I tab-completed from “ag”.) Yay I found it! Looking back at the usage of “agda”, I use “-i” to add import paths. So:

[/home/steve/src/agda][steve@stevebox]$ agda -c -i /usr/share/agda-stdlib test.agda [19:41:40]
The name of the top level module does not match the file name. The
module test should be defined in one of the following files:
/usr/share/agda-stdlib/test.agda
/usr/share/agda-stdlib/test.lagda

Huh? It’s looking for my source file “test.agda” in the import path. This story will be resolved later, but first, a tangent:

Enter Emacs

It was around this time that someone on the IRC channel on which I was asking for help asked if I was using emacs (I wasn’t) and I asked if I should be (and the reply was “yes”).

Emacs is a very extensible text editor with many powerful tools to help programmers. Some extensions exist for various languages that add tools for testing and compiling code from in the editor. One such extension exists for Agda, and it was installed when I apt-got Agda (but all the documentation I read said I should have gotten a “agda-mode” binary with Agda (I didn’t) and when I run that it will install agda-mode in emacs (the name of the agda extension)).

At this point I’ll make readers aware that I use VIM as my editor of choice. I have nothing against emacs, I just happened to be around lots of VIM users when I outgrew gedit (another editor).

So I quickly learnt the basics of emacs. This was a bit frustrating because I’ve spent the better part of the last three years building up muscle memory for VIM shortcuts (dvorak VIM shortcuts mind you), and having to learn an entire new set of commands with lots of Control and Meta key presses was…unpleasant. Nevertheless, emacs’s agda-mode gave me a nice drop-down menu of things to do with Agda code (including compile, evaluate an expression and find the type of an expression).

So I tried compiling my code with the standard library import. I got an error message:

Problem encountered. The *ghci* buffer can perhaps explain why.

(ghci is the name of an interactive Haskell interpretter.)

Nice. This was before I realized that Agda operations are performed through a Haskell interface, and before I learnt all about buffers in emacs, so I was pretty confused by this. I found out that buffers are effectively containers for text. When you open a file in emacs, its contents is copied to a buffer. When you save a file, the buffer is written to the file on disk. Buffers can also exist for non-files, and the ghci buffer is one such example. Since Haskell is used to compile Agda, a ghci session is run which can be accessed in a ghci buffer. It allows you to interact with the ghci shell just as you normally would in a terminal. After the failed compile attempt, I had a look at the buffer:

Alright. So something is going horribly wrong. This first thing that fails (well, the first thing it’s trying to do) is setting the package to “Agda-2.3.0” (the Agda library package for Haskell I installed at the start). But hang on. The version of that package was 2.3.0.1, not 2.3.0. At some point, wires are getting crossed about which version of Agda to load, and the wrong one is being attempted and failing because it doesn’t exist. Ok, so this is an interactive shell, so I can fix this. At the ghci prompt, I ran:

Aww man! Ok so ioTCM is a function for doing Agda magic, but it’s not currently in scope. Loading the package made ghci aware of the existence of some Haskell modules, and ioTCM resides within one of them. In ghci, there is a “:browse” command that lists the functions in a module, and this coupled with some nice tab-completion inside ghci means I can navigate around the modules inside the Agda package. But this doesn’t really help me find the function quickly.

Here’s my solution. Forget about Haskell for a second. Even if these Haskell modules are compiled code, in order for them to be of any use, people have to be able to call functions from inside them using a function call in source code. For this to work, the name of each function probably exists in plain text somewhere in the module file which contians it. And how do we find a string inside a file inside a directory structure? GREP!

And compile again. The long pause means that it works. It will have compilation errors, but at least the compiler is being invoked. Success.

Now let’s do something useful

…where useful is context sensitive and this is the context of learning Agda. When I was learning Haskell, the most valuable tool by far was ghci (yes, the prompt that I just fought to get my Agda to compile). It lets you enter Haskell expressions and it will print out what the expression returns. You can define functions, and then call them. It lets you load a Haskell source file and use functions and types defined in that file in the interactive shell. Here’s an example:

Haskell is strongly typed, and as a result, it’s much easier to encounter type errors than in say, perl. Sometimes, it’s useful to confirm the types of expressions with Hasell’s type checker before using them. ghci can do this:

As more information gets encoded in the type system, this tool becomes more and more useful. In Agda, the type system is more powerful than in Haskell, and more information can be encoded in it. As such it would be very useful to have a similar tool. I asked if such a tool was available on the IRC channel and was told that in emacs, C-c C-d can be used to check the type of an expression. Similarly, C-c C-n can be used to evaluate or “normalize” an expression.

But I missed the way it worked in ghci. In emacs, I can’t see my history as I enter new expressions to infer types or normalize. Doing it all through emacs just felt too constrictive.

Remember how when I did anything Agda the Haskell function being called would be sent to the ghci buffer. When I use emacs to infer types or normalize, I can see the Haskell function call being made. I jumped into my own ghci shell in a terminal and tried to reproduce the results:

There is a lot of superfluous information there, but the value and type of the expression “a” is displayed. Knowing the Haskell functions that get this information, I knocked together a command line program that behaves similarly to ghci for type inferring and expression evaluation.

So it still prints the same stuff as before but now there is a nice wrapper. I might make a little perl script to wrap this to scrape out the meaningful information in the future.

Compiling from a terminal

I almost forgot. I was having this problem:

[/home/steve/src/agda][steve@stevebox]$ agda -c -i /usr/share/agda-stdlib test.agda [19:41:40]
The name of the top level module does not match the file name. The
module test should be defined in one of the following files:
/usr/share/agda-stdlib/test.agda
/usr/share/agda-stdlib/test.lagda