Haskell Introduction

by "Blag" - Developer Evangelist

Return to Geeky Thursday

What is Haskell?


Haskell is a general-purpose purely functional programming language.


Is a lazy evaluation functional language...which means that nothing is evaluated until really needed.


It's Open Source.


Makes you throw away all your previous programming dogmas...really...


I mean it...Really!

How to install Haskell?


Haskell can be downloaded from here Haskell

It's available for Windows, Linux and Mac.

Windows version comes with a really nice shell.

For Linux or Windows we can (and we're going to use) Geany.

If you're on Mac follow this Geany OSX.

Who uses Haskell?


  • Facebook -> Used internally for tools. Lex-pass is a tool for programatically manipulating a PHP code base via Haskell
  • AT&T -> Network Security division to automate processing of internet abuse complaints.
  • Bank of America -> Backend data transformation and loading.
  • Intel -> Developer a Haskell compiler as part of their research on multicore parallelism at scale.
  • Microsoft -> Bond, a cross-platform framework for working with schematized data.
  • NVIDIA -> Handful of in-house tools.

Starting out...


To begin with...we're going to create a file called "ghci.conf" on Home/.ghc.

:set prompt "ghci> "


Go to a terminal a do the following...

chmod g-w ~/.ghc/ghci.conf


On Windows, simply type the commands on WinGHCi..

On Linux/Mac type "ghci" in the Terminal/Console.


Variables


Variables are not variable...

Once assigned...variables cannot change...they're immutable...

However, in the terminal/shell we can use the let command to assign/reassign...

				
let myvar = 5

myvar

5


let myvar = "The value changed!"

myvar

"The value changed!"
				

Strings in Haskell are really a list of characters.


Haskell will determine the variable type when a value is assigned, however for functions the type must be declared.


:t allows us to find a variable's type.


				
let myvar = "This is a variable!"

:t myvar

myvar :: [char]
				

Variable can't change their values after assignment...


So how can we update their values? We can't...but we can update the value when calling a function...


Its value doesn't really change but it's carried out by the function...


Haskell strongly relies on recursion, so this makes a lot of sense.


Tuples

Sometimes we need to group values together...for that, we can use Tuples.

When using 3 values...they're called Triples...4 values is a 4-Tuple and so on...

				
let myvar = (1,"Blag")

myvar

(1,"Blag")



let myvar = (1,"Blag","SAP")

myvar

(1,"Blag","SAP")
				

We can extract the Tuples values using fst and snd.


				
let myvar = (1,"Blag")

fst myvar

1



snd myvar

"Blag"

				

When using Triples, 4-Tuple and so on...we need to create a function...we'll see that later...

List


Lists are the most common and used variable type in Haskell.


Lists comes with some nice built-in functions...

				
let someNumbers = [1,2,3,4,5]

someNumbers

[1,2,3,4,5]



let someNames = ["Blag","Schmerdy","Rocky"]

someNames

["Blag","Schmerdy","Rocky"]
				
				
let someNumbers = [1,2,3,4,5]

head someNumbers

1


tail someNumbers

[2,3,4,5]


last someNumbers

5


init someNumbers

[1,2,3,4]
				
				
someNumbers !! 3

4


take 3 someNumbers

[1,2,3]


let hello = "Hello"

head hello

'H'


take 2 hello

'He'
				
				
[1,2,3] ++ [4,5,6]

[1,2,3,4,5,6]



"Hello " ++ "World!"

"Hello World!"



1 : [2,3,4,5]

[1,2,3,4,5]



elem 2 [1,2,3,4,5]

True



elem 6 [1,2,3,4,5]

False
				

Functions


Function are very important...everything is a function.


There's no such things as Classes or Objects.


We can define the same function name with different number of parameters or even different values.


They will be treated as completely different functions.

First Application


For our First Application we need to wrote the code on any editor. We need to use the .hs extension


Then we need to load the file using :l FileName and then simply call our function.


On Geany we need to press the button Run or view the current file...but we still need to use :l filename -:P


Call your file "triples.hs" (all in lowercase).

				
first :: (a,b,c) -> a

first (x,_,_) = x



second :: (a,b,c) -> b

second (_,y,_) = y



third :: (a,b,c) -> c

third (_,_,z) = z
				

When we run it we're going to see...


Second Application


In this example we're going to use the same function name with different value parameters...


Call your file "greetings.hs" (all in lowercase).

				
greet :: String -> String -> String

greet("male") name = "Good Morning Mr. " ++ name

greet("female") name = "Good Morning Mrs. " ++ name

greet _ name = "Good Morning ??? " ++ name
				

When we run it we're going to see...


List Comprehensions


I told you...lists are very important -;).


List comprehensions allows us to apply an operation or function to each value of the list.


				
[x * 10 | x <- [1..10]]

#[10,20,30,40,50,60,70,80,90,100]



[x * 10 | x <- [1..10], x * 10 > 50]

#[60,70,80,90,100]



let doubleIt x = x * 2

[doubleIt x | x <- [1..10]]

#[2,4,6,8,10,12,14,16,18,20]
				

Recursion


Recursion is one of the key points in Haskell...you call a function that calls itself multiple times.


As we can't change the value of a variable, we can pass different values as parameters. This way we can update the variable value without changing the variable value...


Also, we can use something called "Pattern Matching" which is used to determine which function to call...


Third Application


In this example we're going to create a Fibonacci sequence generator...


Call your file "fibonacci.hs" (all in lowercase).


				
showFib :: Int -> IO()

showFib(num) = do

    -- print $ fib num 0 1
    
    putStr $ unwords $ map show $ fib num 0 1
    
    putStr "\n"
    
    
    
fib :: Int -> Int -> Int -> [Int]    

fib num a b

    | a > 0 && num > 1 = [a+b] ++ fib (num-1) (a+b) a
    
    
    | a == 0 = [a,b] ++ [a+b] ++ fib (num-1) (a+b) b
    
    
    | num == 1 = []    
				

When we run it we're going to see...


Fourth Application


In this example we're going to create an LED Number


Call your file "led.hs" (all in lowercase).


				
showLED :: Int -> IO()

showLED(num) = do

	putStr(get_led (digits num) 0 num)
				
				
get_led :: [Int] -> Int -> Int -> String

get_led (x:xs) n num = leds !! x !! n ++ 

                       get_led(xs) n num

	where leds = [[" _  ","| | ","|_| "],

                      ["  ","| ","| "],

                      [" _  "," _| ","|_  "],

                      ["_  ","_| ","_| "],

                      ["    ","|_| ","  | "],

                      [" _  ","|_  "," _| "],

                      [" _  ","|_  ","|_| "],

                      ["_   "," |  "," |  "],

                      [" _  ","|_| ","|_| "],

                      [" _  ","|_| "," _| "]]
				
				
get_led [] n num

	| n < 2 = "" ++ "\n" ++ 
	
	          get_led(digits num) (n+1) num
	
	
	| n == 2 = "" ++ "\n"



digits :: Int -> [Int]

digits = map (read . (:[])) . show
					
				

When we run it we're going to see...


Fifth Application


In this example we're going to create a Decimals to Romans application


Call your file "dectoromans.hs" (all in lowercase).


				
showRomans :: Int -> IO()

showRomans(num) = do

	putStr $ concat $ get_roman num 0	
				
				
get_roman :: Int -> Int -> [[Char]]


get_roman num ctr

	| num >= roman = [snd $ roman_nums !! ctr] ++ 
	
	                  get_roman(num - roman) ctr

	| num < roman && num > 0 = get_roman(num) 
	                           
	                           (ctr+1)

	| num <= 0 = ["\n"]

	where roman = fst $ roman_nums !! ctr

	      roman_nums = [(1000,"M"),(900,"CM"),
	      
                            (500,"D"),(400,"CD"),
                            
                            (100,"C"),(90,"XC"),(50,"L"),
                            
                            (40,"XL"),(10,"X"),(9,"IX"),
                        
                            (5,"V"),(4,"IV"),(1,"I")]
				

When we run it we're going to see...


Sixth Application


In this example we're going to read a file and count how many time a letter appears...


Call your file "countletters.hs" (all in lowercase).


Create a file called "readme.txt" with the following text...


"This is a text file that we're going to read it using Haskell"


				
import System.IO

import Data.List



main = do

    contents <- readFile "readme.txt"
    
    print $ numletters contents
    
    
    
letters :: String -> [String]

letters = map ((:[]))



numletters :: String -> [(String,Int)]

numletters xs = map(\ws -> (head ws, length ws)) $

                    group $ sort $ letters xs
				

When we run it we're going to see...


GUI Programming


Haskell provide many libraries to make GUI applications...


One of the most used is wxHaskell which is based on C/C++ wxWidgets...


This one is considered a Medium-Level library...


wxHaskell Download


This app will ask for a name and display a greeting...


Call your file "wxhaskell.hs" (all in lowercase).


				
module Main where

import Graphics.UI.WX

main :: IO ()

main = start hello

hello :: IO ()

hello = 

    do f <- frame [text := "Hello!"]

       p <- panel f []

       name <- textEntry p [text := ""]

       b <- button p [text := "Greet!"]                  

       l <- singleListBox p []
				
				
       set b [on command := greet p l name]

       set p [layout := (column 2 [

                        (row 2 [fill $ widget name, 
                        
                                widget b]),

                         fill$widget l ])]

       set f [layout := minsize (sz 300 100) $ widget p]

     where

         greet p l name = 

             do nametext <- get name text

                let greetme = "Welcome to WxHaskell! " ++

                               nametext

                set l [items := [greetme]]
				

When we run it we're going to see...


That's it for now...


I hope you had some fun...


Functional languages are very important


because they force you think differently...


and getting the grasp of Haskell is not an easy thing...


Contact Information


Blag --> blag@blagarts.com

@Blag on Twitter

Go back home...