Haskell

Appeared in:
1990
Influenced by:
Influenced:
Paradigm:
Typing discipline:
File extensions:
.hs, .lhs
Dialects:
Versions and implementations (Collapse all | Expand all):
Programming language

A purely functional non-strict programming language with an expressive type system.

Elements of syntax:

Inline comments --
Nestable comments {- ... -}
Variable declaration variable :: type {optional}
Variable declaration with assignment variable = value {toplevel} or ... where variable = value or let variable = value in ... {local scope}
Block { ... }
Deep equality ==
Deep inequality /=
Comparison < > <= >=
Function definition f p1 p2 ... = ... or f = \p1 p2 ... -> ...
Function call f a b ...
Function call with no parameters f {in a monad}
Sequence ; {alternative to using line alignment for let, where, and do blocks}
If - then when condition (...) {monad}
If - then - else if condition then ... else ...
Loop forever forever {monad}
For each value in a numeric range, 1 increment map expr [1..n] or mapM monad [1..n]
For each value in a numeric range, 1 decrement map expr [n,n-1..1] or mapM monad [n,n-1..1]

Examples:

Hello, World!:

Example for versions GHC 6.10.4
module Main where

main = do
    putStrLn "Hello, World!"

Factorial:

Example for versions GHC 6.10.4

This example uses recursive factorial definition and consists of three major parts:

  • definition of factorial function, which takes one argument of Integer type (integer number of unlimited precision) and returns the same type. The function is defined recursively, and types of argument and return are given explicitly to avoid ambiguity.
  • definition of line function, which prints the number and its factorial in required format. Use of
    printf command is the same as in C++.
  • printing the numbers and their factorials themselves. [0..16] creates a list of numbers from 0 to 16, inclusive. Function map applies first argument (line function) to each element of second argument ([0..16] list) and as a result creates a list of so-called “output actions” (which can be used as values in Haskell). To combine these actions in one we use sequence_ command, which is applied to a list of actions, executes first action from the list and recursively applies it to the tail of the list. But for simplicity, we use mapM_, which combines map and sequence_.
module Main where

import Text.Printf

factorial :: Integer -> Integer
factorial 0 = 1
factorial n = n * factorial (n - 1)

line x = printf "%d! = %d\n" x $ factorial x

main = mapM_ line [0..16]

Fibonacci numbers:

Example for versions GHC 6.10.4

This example uses one of the main Haskell features — lazy evaluations and infinite lists. Infinite list of Fibonacci numbers fibs is defined using zipWith function which applies its first argument (a function of two variables, in this case +) to pairs of corresponding elements of second and third arguments (lists). tail fibs returns tail of the list fibs (i.e., all elements except for the first one). Thus first element of the list returned by zipWith is a sum of first and second elements of list fibs and becomes its third element.

module Main where

import Text.Printf

fibs :: [Int]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

line n = printf "%d, " $ fibs !! n

main = do
    sequence_ $ map line [1..16]
    putStrLn "..."

Fibonacci numbers:

Example for versions GHC 6.10.4

This example uses recursive definition of Fibonacci numbers via pairs of adjacent numbers in the sequence. Only first elements of the pairs are printed.

module Main where

import Text.Printf

fibNextPair :: (Int, Int) -> (Int, Int)
fibNextPair (x, y) = (y, x+y)

fibPair :: Int -> (Int, Int)
fibPair n 
    | n == 1 = (1, 1)
    | otherwise = fibNextPair (fibPair (n-1))

line n = printf "%d, " $ (fst.fibPair) n

main = do
    sequence_ $ map line [1..16]
    putStrLn "..."

Factorial:

Example for versions GHC 6.10.4

This example uses the Prelude function product, which computes the product of a list of numbers. When the list is empty, it returns 1 (the multiplicative identity), so this works for 0 too.

module Main where

factorial :: Integer -> Integer
factorial n = product [1..n]

line x = putStrLn $ show x ++ "! = " ++ factorial x

main = mapM_ line [0..16]

Factorial:

Example for versions GHC 6.10.4

This example performs a “fold” using the function foldl (which is a left-fold, but since multiplication is associative, left fold and right fold are the same) to fold multiplication over the list [1..n]. We provide the “initial value” 1, so that it will produce 1 when the list is empty.

module Main where

factorial :: Integer -> Integer
factorial n = foldl (*) 1 [1..n]

line x = putStrLn $ show x ++ "! = " ++ factorial x

main = mapM_ line [0..16]

Quadratic equation:

Example for versions GHC 6.10.4

Haskell provides complex datatype. Function quadratic accepts a list of complex numbers and returns a list of equation roots. Notation root sign allows to generalize the notation of roots for two signs of square root.

module Main where

import Data.Complex
import System.IO (hFlush, stdout)

quadratic :: (Complex Double, Complex Double, Complex Double) -> [Complex Double]
quadratic (0, _, _) = []
quadratic (a, b, c)
      | d == 0 = [root (+)]
      | otherwise = [root (+), root (-)]
  where d = b*b - 4*a*c
        root sign = sign (-b) (sqrt d) / (2*a)

main = do
    putStr "A = "
    hFlush stdout
    a <- readLn :: IO Double
    putStr "B = "
    hFlush stdout
    b <- readLn :: IO Double
    putStr "C = "
    hFlush stdout
    c <- readLn :: IO Double
    print $ quadratic (realToFrac a, realToFrac b, realToFrac c)

Fibonacci numbers:

Example for versions GHC 6.10.4

This is another example which uses lazy evaluation and a different, shorter form of producing output in required format.

main = putStrLn $ withDots $ join $ take 16 fibs
       where fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
             join = foldl (\a b -> a ++ show b ++ ", " ) "" 
             withDots = (++ "...")