Haskell Tutorial – Part 2

NOTIFICATION: These examples are provided for educational purposes. The use of this code and/or information is under your own responsibility and risk. The information and/or code is given ‘as is’. I do not take responsibilities of how they are used. You are welcome to point out any mistakes in my posting and/or leave a comment.

Haskell Signatures

Previously, we saw how to check the type of the function map:

Hugs> :t map
map :: (a -> b) -> [a] -> [b]

Haskell have a peculiar way to express types.

One way to interpreting this is the following:

map :: (a -> b) -> [a] -> [b]
map ::   {- is the function name -}
(a -> b) {- This means that map takes a function as a argument -}
-> [a]   {- This means that map also takes an array of element type a as an argument -}
-> [b]   {- And return an array of elements type b -}

However, Haskell work using currying, therefore the another way to see this is the following:

map :: (a -> b) -> [a] -> [b]
map ::   {- is a function -}
(a -> b) {- that takes a function as a argument and return a new function (we called map_1) -}
-> [a]   {- This new function (map_1) will take an array of type a as an argument -}
-> [b]   {- and will return an array of element of type b -}

In Haskell, currying is supported in order to support first-class functions. For example:

  1. Lets assume a function takes two arguments; however, only one argument will be supplied
  2. The function will be “curried” which means that  it will produce a function of one argument (one that is not supplied)
  3. Therefore we could see it in this way:
    fn :: a -> b -> c

    where fn(a) yields a new function

    fn' :: b -> c

    in which fn'(b) is called to produce c

For example, lets say we wish to obtain the square root of the values 2 and 3 which are in a list, and return a new list with the results:

[2, 3] => [1.41..., 1.73...]

We can use map together with the function sqrt (square root)!
If we check the type of sqrt we will find that:

Hugs> :t sqrt
sqrt :: Floating a => a -> a

This is a function that takes an element of type a as argument and return an element of type a as a result.
If we use it together with map, we obtain:

Hugs> :t map sqrt
map sqrt :: Floating a => [a] -> [a]

This means that when map takes sqrt function as a parameter, it will create a new function that will take an array of type a and return an array of type a.

Now let see it in action:

Hugs> map sqrt [2, 3]
[1.4142135623731,1.73205080756888]

Now, lets analyse what could be happening internally in Haskell when this command line is executed:

  1. The code of map is the follow:
    -- Map and append
    map :: (a -> b) -> [a] -> [b]
    map f []     = []
    map f (xMads) = f x : map f xs
  2. The code of sqrt is the follow:
    class  (Fractional a) => Floating a  where
    ...
    exp, log, sqrt      :: a -> a
    (**), logBase       :: a -> a -> a
    ...
    x ** y           =  exp (log x * y)
    sqrt x           =  x ** 0.5

When we execute:

> map sqrt [2, 3]

  1. map sqrt [2, 3] 

    match with

    > map f (xMads)
  2. Therefore,
    f x : map f xs

    is executed in which f is sqrt, x is the first element of the list, and xs is the rest of the list

    sqrt 2 : map sqrt [3]
  3. Then
    map sqrt [3]

    match again
    f x : map f xs

    and is executed again to  obtain

    sqrt 2 : sqrt 3 : map sqrt []
  4. map sqrt []
    match
    map f [] = []
    obtaining
    []
  5. Then we obtain
    sqrt 2: sqrt 3 : [] 
  6. Finally, the functions are executed and we obtain
    1.4142135623731 : 1.73205080756888 : [] 

    which returns

    [1.4142135623731, 1.73205080756888]

The following are some examples (fn means function) of types:

  1. fn is just a value:
    fn :: x
  2. fn return a list of ys
    fn :: x -> [y]
  3. fn return a typle of (y, z)
    fn :: x -> (y, z)
  4. fn is a higher order function. It takes a function for argument (b->c) as an input an return a function Foo
    fn :: (b -> c) -> Foo
  5. fn is an input/output action tha return an int value
    fn :: x -> IO Int
Share

Haskell Tutorial – Part 1

NOTIFICATION: These examples are provided for educational purposes. The use of this code and/or information is under your own responsibility and risk. The information and/or code is given ‘as is’. I do not take responsibilities of how they are used. You are welcome to point out any mistakes in my posting and/or leave a comment.

You are required to install Hugs in your system. I believe you can download it at this address: <http://hackage.haskell.org/platform/>. The Haskell platform is available form Windows® , Mac®, and Linux. For Debian distribution and derivation distributions such as Ubuntu, you can execute the following command line:

sudo apt-get install hugs

For editors, you can search on Internet. I personally use gedit.

A Little About Haskell

Haskell is a purely functional programming language which means that inputs will be applied on a  mathematical function that will produce an output. There are no internal state; therefore, there is no possible side effects of the output. Also, Haskell is a strongly typed language.

At different of some imperative languages, Haskell provide:

  1. First-class function values: Normally, they can be passed as a parameter, assigned into a variable, and/or returned from a subroutine
  2. Higher-order functions: They are functions that can take a function as an argument, and/or return a function.
  3. Polymorphism / static polymorphism typing: Thorough mechanism of type inference, a function can be used on a general class of arguments.
  4. Monads: They allow the programmer to put together a sequence of actions that will be executed in a determined order. They are a solution to the problem of threading mutable state through a functional program.
  5. Monadic I/O, random numbers, mutable global variables, and shared-memory synchronization.
  6. Pattern matching
  7. Curried functions: A function with multiple arguments is replace with a function that takes a single argument and return a function with the remaining arguments.
  8. Non-strict semantics.
  9. Indentation-based (also known as layout) syntactic grouping.
  10. List type and list comprehension
  11. Operators.
  12. Structured function returns.
  13. Constructors (also known as aggregates) for structured objects.
  14. Garbage collection: The main purpose of garbage collection is to free memory after an object stop to be required so other program can use the free space.

Haskell apply lazy evaluation. This means that any evaluation will be evaluated if and only if the system required the evaluation to be evaluated. Also, it keep track of which evaluation have been already evaluated and keep the result in case it is needed more than once.

Typing Your First Message to The World and Play Around

Type Hugs on your command line and when you see Hugs> type putStr “Hello World!”

carlstein@your-computer:~$ hugs
__   __ __  __  ____   ___      _________________________________________
||   || ||  || ||  || ||__      Hugs 98: Based on the Haskell 98 standard
||___|| ||__|| ||__||  __||     Copyright (c) 1994-2005
||---||         ___||           World Wide Web: http://haskell.org/hugs
||   ||                         Bugs: http://hackage.haskell.org/trac/hugs
||   || Version: September 2006 _________________________________________

Haskell 98 mode: Restart with command line option -98 to enable extensions

Type : ? for help
Hugs> putStr 'Hello World'
Hello World!

Hugs> putStr 'You can do Math too!'
You can do Math too!

Hugs> 4 * 4
16

Hugs> 4 `div` 2
2

Two different Style of Haskell

There are two ways to write a Haskell file;

  1. Traditional Haskell style:
    1. Files have the extension .hs
    2. Functions begin in the first column, any additional line of code must be indented.
    3. Any other new function definition must began after then end of previous (first function) function definition.
    4. One-line comments are prefixed with ‘- -‘
      -- This is an example of one-line comment
    5. Multiple-lines comments are began with ‘{-‘ and ends with ‘-}’
      {- This is an example
          of multiple-lines comments -}
  2. Literal Haskell style:
    1. Files have the extension .lhs
    2. Every line is considered a comment.
      This is a multiple line comment
      This is another line of comment
    3. Code begin with ‘>’. Comments must be separated from the line of code by one space before and after the line of code.
      This is a comment is before the code
      
      > putStr 'Line one of code'
      > putStr 'Line two of code'
      
      This is a comment after the code
    4. A definition will end when the first piece of text (code or comments) lies at same indentation
    5. A definition will end when the first piece of text (code or comments) lies to the left of the start of the definition
    6. All definitions must begin at the same level of indentation
    7. Begin your files with defining them as a module
      > module Example1
      >     where

      Notice that a module begin with capital letter.

    8. To load your module type in hugs:
      Hugs> :load YourModuleName

      or

      Hugs> :l YourModuleName

      In either case, if there are not any errors the prompt of hugs should change to the name of your module:

      YourModuleName> 

We are going to focus these tutorial on Literal Haskell.

Libraries in Haskell

By default the programmer have the Prelude library at disposition. This is a default library that hold in-build functions. In order to include other libraries you can use import

>   module Example1 where
>   import List

Other libraries may be loaded together with the list library such as Prelude.hs, Maybe.hs, and List.hs.

A list of libraries available for the programmer can be fount at <http://www.haskell.org/ghc/docs/latest/html/libraries/>.

Defining Constants

>   module Example1
>     where

This define a constant 

>   valuePi :: Double
>   valuePi = 3.14159

If we wish to know the type of valuePi we could use the following command ‘:t’

Hugs> :l Example1

Example1> :t valuePi
valuePi :: Double

Some basic type are: Int, Bool, Char, Float, Double, Integer, …
String is a list of characters. Prelude defines string

type String = [Char]

In Haskell, type is the equivalent of typedef in C

Function Definitions
There are two way to define a function:

  1. Implicity:
    > module Example2a where
    > cubeValue x = x * x^2
  2. Explicity:
    > module Example2b where
    > cubeValue2 :: Int -> Int
    > cubeValue2 y = y * y^2

In both cases (implicit and explicit), “=” means ‘defined as‘ and “::” means ‘has type

Factorial Examples:
In the following example, we are showing: if/then/else statements, how indentation is performed, and how guards are used.

>module Example3 where

>   factorial :: Int -> Int
>   factorial x = if (x < 0) then error 'y can't be negative' else if (x==0) then 1 else x * factorial(x-1)

>   factorial2 :: Int -> Int
>   factorial2 y
>       | y < 0     = error 'y can't be negative'
>       | y == 0    = 1
>       | otherwise = y * factorial(y - 1)

Regular Fibonacci Examples:

> module Example4 where

> fibonacci n
>     | n == 0 = 1
>     | n == 1 = 1
>     | otherwise = fibonacci (n - 1) + fibonacci (n - 2)

Another way to write it

> fibonacci2 0 = 1
> fibonacci2 1 = 1
> fibonacci2 n = fibonacci2 (n - 1) + fibonacci2 (n - 2)

Using where clause

> fibonacci3 0 = 1
> fibonacci3 1 = 1
> fibonacci3 n = fibMinusOne n + fibMinusTwo n
>     where
>     fibMinusOne n = fibonacci3 (n - 1)
>     fibMinusTwo n = fibonacci3 (n - 2)

If you wish you can check the type of these functions:

Example1> :l Example4

Example4> :t fibonacci
fibonacci :: (Num a, Num b) => a -> b
Example4> :t fibonacci2
fibonacci2 :: (Num a, Num b) => b -> a
Example> :t fibonacci3
fibonacci3 :: (Num a, Num b) => b -> a

Tuples

For those who are C programmers, I would say that tuples are non-homogeneous linear structures
such  as structures in C. In C, we could have the following structure:

struct Person{
  char * fullName;
  int age;
} employee;

employee.fullname = &mathias_name; // Assuming mathias_name hold to a string 'mathias'
employee.age = 25;

In Haskell, we obtain the same in the following fashion:

> module Example5 where
> type Person = (String, Int)
> employee :: Person
> employee = ('Mathias', 25)

notice that Person goes with the first letter in capital since it is not a variable.

If we wish to obtain the name and age of the employee we can use fst and snd

Hugs> :l Example5
Example5> fst employee
'Mathias'
Example5> snd employee
25

fst is a function that return the first element of the tuple, while snd is another function that returns the second element of the tuple.

fst (x,y) = x
snd (x,y) = y
Share