33

Many of the Haskell tutorials I've looked through focus almost entirely on syntax with very little coverage on how to structure a program.

For example...

Here's a bare-bones outline of a C++ application:

#include <iostream>
using namespace std;

int addition (int a, int b)
{
  int r;
  r=a+b;
  return (r);
}

int main ()
{
  int z;
  z = addition (5,3);
  cout << "The result is " << z;
  return 0;
}

When I first started learning C++, examples like these helped me immensely in learning how to assemble individual pieces into working programs. Maybe I'm looking in the wrong places, but I haven't been able to find any such examples that are as direct and simple for Haskell.

I already know A LOT of Haskell syntax. I can write recursive list comprehensions, and manipulate strings, integers, and lists out the wazoo.

In short: I just want to know what two subroutines and variable pass looks like in Haskell. If I can get some basic understanding on how to structure a Haskell program, I might finally be able to put all the syntax I've learned to some use.

recursion.ninja
  • 5,377
  • 7
  • 46
  • 78
subtlearray
  • 1,251
  • 1
  • 11
  • 23
  • 2
    I'd start at places like http://www.haskell.org/haskellwiki/Haskell_in_5_steps I'm learning Clojure. However, I do have the O'Reilly Haskell book, and this book -- http://www.nostarch.com/lyah.htm -- seems to be getting a lot of good reviews. – octopusgrabbus Feb 05 '12 at 22:20
  • 3
    While this is a legitimate question, allow me to suggest that you are approaching Haskell slightly wrong. Haskell emphasizes pure functions as much as possible, and most Haskell implementations provide a REPL (read-eval-print loop) where you can play around with functions you have defined. I highly recommend, instead of making small programs that print to stdout, just write functions and play with them in ghci. I think you'll find it's much more flexible and fun for learning Haskell. – Dan Burton Feb 05 '12 at 23:21
  • @DanBurton I've probably spent the last month reading up on syntax, and playing around with functions and list comprehensions in ghci. I'm ready to make a program now. (:D You're right in that I have been approaching Haskell wrong. I'm trying to apply procedural programming principles to a functional programming language. I'm still trying to wrap my head around how to turn a bunch of functions into something that can do more than run once and stop. I'll keep reading. – subtlearray Feb 06 '12 at 00:31
  • @octopusgrabbus This is my first time seeing the Haskell in 5 Steps link. From what I gather, I can make a Haskell program by having main call and loop through various functions listed beneath it? – subtlearray Feb 06 '12 at 00:41
  • I don;t know Haskell, but it is -- from what I have heard a difficult language to learn. I started diving into Clojure, but there is a lot more to learn than the syntax. Suggest learning Haskell might require the same treatment, hence the link to that book and the Haskell Wiki. – octopusgrabbus Feb 06 '12 at 13:26
  • 1
    @SubtleArray: there's no "beneath": in Haskell, the functions could be in any order in the source file. – amindfv Feb 16 '12 at 06:54

1 Answers1

34

A Haskell program's structure is surprisingly simple. You have a main function which does IO, and that's about it. So the basics:

module Main where

addition a b = a + b

main :: IO ()
main = do let z = addition 5 3
          putStrLn $ "The result is: " ++ show z

Now you can compile this into a simple program using something like:

ghc --make Main.hs -o program

and it should produce an executable called program.

In general, programs are structured as mostly pure functions doing the actual computation coupled with discrete parts of the code dealing with the IO. (There are of course exceptions to this, but the general idea of writing as much pure code as possible is fairly universal.)

Since almost everything is expressed as a bunch of pure functions, you do not pass variables between them--the functions communicate by passing arguments.

The part of your code that does IO is anchored in main. In most cases, all your IO is going to go through main; even if you write IO actions separately and give them names, they will ultimately be executed starting from main.

A "function group" in Haskell is called a "module". You can have multiple modules, each in its own file:

module Blarg (exportedFunction) where

helper a b = ... -- this will *not* be exported
exportedFunction a b = helper a b -- this *will* be exported

Only the identifiers in the parentheses will actually be exported; the rest are hidden. If you do not include the parentheses at all, everything will be exported by default.

Save this file as Blarg.hs. Now you can import it in Main:

import Blarg

Another useful way to group functions is where:

complicatedFunction a b c = helper 0
  where helper count = ...

This way helper is only in scope for complicatedFunction and also has access to a, b and c from complicatedFunction.

Tikhon Jelvis
  • 67,485
  • 18
  • 177
  • 214
  • Thank you for your reply. I'm familiar with main, but how do I make other subroutines, and have those subroutines communicate and pass variables between each other? – subtlearray Feb 05 '12 at 22:22
  • 3
    You don't really have "subroutines", you have *functions*. Since there is no mutation, you pass values around as arguments to those functions (like `addition 5 3` in my example). – Tikhon Jelvis Feb 05 '12 at 22:23
  • Right. I meant to say, how do you make other "function groups"? Basically, I'm trying not to put everything in main. – subtlearray Feb 05 '12 at 22:26
  • See this wiki page for information about Haskell Modules: http://www.haskell.org/tutorial/modules.html – dflemstr Feb 05 '12 at 22:27
  • @dflemstr: That's not a wiki page, that's the Gentle Introduction :) – ehird Feb 05 '12 at 22:36
  • I see! I was using the wrong terminology, like "subroutine" and "data structure." What I wanted were "modules." Thank you very much for your time and help. – subtlearray Feb 05 '12 at 22:42
  • @ehird, that is very true, although I wish it was a wiki page, so much in fact that I managed to convince myself for a second! – dflemstr Feb 05 '12 at 22:44
  • @TikhonJelvis: You say "in most cases": in what cases do functions of type IO not go through `main`? – amindfv Feb 16 '12 at 06:56
  • @amindfv: There is a function called `unsafePerformIO` which lets you do IO anywhere. However, it is (as the name unsubtly hints) *unsafe* and you should probably never need to use it. (It finds use in libraries like `System.Random`.) – Tikhon Jelvis Feb 16 '12 at 07:15