the cedar ledge

Notes on Programming in Haskell

Date: November 3 2021

Summary: My notes on an overview and summary on how to use Haskell

Keywords: #syntax ##summary #haskell #programming #languages #archive

Bibliography

Not Available

Table of Contents

    1. Packages
    2. Functions
      1. Ar
    3. Haskell Type System
      1. Bool
      2. Char
      3. String
      4. ()
      5. Type Coercion
    4. Pattern Matching
    5. Syntax
      1. Loops and Recursion
      2. Guards
      3. Types
      4. Functions
        1. Defining Function in ghci
        2. Defining Function in a Script
        3. Variable Wildcards
      5. Function Composition
      6. Double colons
      7. Infix Operators
    6. Equality
      1. Functional Equality
      2. Extensional Equality
    7. Examples
      1. Print "Hello World!"
      2. Reload a Loaded File
  1. How To Cite
  2. References:
  3. Discussion:

Packages

Prelude - Haskell's Standard Library Data - Common abstract data type manipulations for use within Haskell

Functions

All functions are pure within Haskell. This means that the same result is always produced with no side effects given the same input to a Haskell function.

Haskell functions are lazy. They do not evaluate until needed.

Ar

Haskell Type System

Except only in very seldom cases, type annotations are optional in Haskell.

Bool

A two element set of True and False.

Char

A set of all Unicode characters.

String

A synonym for an infinite list of Char's.

()

A dummy value where there is only one instance of it ever. It is pronounced unit.

-- Unit typing example

-- Function declaration
f44 :: () -> Integer

-- Function definition
f44 () = 44

-- Function invocation
f44 () -- Returns the value 44

Type Coercion

Haskell provides unsafeCoerce to bypass the type system.

Pattern Matching

Example:

is_zero 0 = True
is_zero _ = False

Syntax

Loops and Recursion

Loops do not exist in Haskell! Rather, to do looping, one must use recursion. Here is a Haskell example that calculates the factorial of a number:

fac n = do
  if n <= 1
    then 1
  else
    n * fac (n - 1)

Guards

Requires a boolean expression that determines the definition of a function. Used most often in recursion. Example:

-- Generates a list from a given series of terms
asc :: Int -> Int -> [Int]
asc n m 
  | m < n = []
  | m == n = [m]
  | m > n = n : asc (n + 1) m

Types

All concrete types start with a capital letter. Names of type variables start with a lowercase letter.

Functions

A function type is created by putting an arrow between two types.

f :: foo -> bar

A function definition uses the name of the function and formal parameters. The body of a function follows an equals sign. Furthermore, the body of a function is always an expression.

One of the strangest quirks about Haskell functions is that arguments are neither surrounded by parentheses nor separated by commas.

Defining Function in ghci
-- Defining a function within ghci
-- Requires the use of multiple lines as denoted
-- by :{ ... :} 
« Prelude » λ> :{
Prelude| add :: Integer -> Integer -> Integer -- Function declaration
Prelude| add x y = x + y -- Function definition
Prelude| :}

« Prelude » λ> (add 5 3) -- Compute sum of two numbers
8
Defining Function in a Script
-- Creating function declaration
add :: Integer -> Integer -> Integer

-- Creating function definition
add x y = x + y

-- Compute sum of two numbers
add 5 3
Variable Wildcards

Arguments can be discarded with a wildcard by the following notation:

fInt :: Integer -> ()
fInt _ = ()

Function Composition

Functions can be composed by putting a period between them (or a Unicode circle, "◦"):

-- Define two functions:
f1 :: A -> B
f2 :: B -> C

-- Compose them together:
f1 . f2

-- Or use alternative composition syntax:
f1 ◦ f2

Double colons

In Haskell, a double colon means, "has type of..."

f :: foo -> bar

Infix Operators

Any infix operator can be turned into a two-argument function by surrounding them with parentheses:

"Hello " ++ "world!"

Can be rewritten as:

(++) "Hello " "world!"

Equality

Functional Equality

Haskell enables you to express equality of functions:

mappend = (++)

This is also known as point-free equality as the arguments to these functions are not defined.

Extensional Equality

Haskell defines extensional equality loosely where

mappend s1 s2 = (++) s1 s2

is saying that the output of the function of the left is equivalent to the output of the function on the right. This is also known as point-wise equality as the arguments (points) are defined.

Examples

This goes in a script called hello.hs

main = do
    putStrLn "Hello World!"

To load it within ghci, open ghci within the same repository that houses the script then run in gchi:

  1. :load "hello.hs"

  2. :main

And here would be the respective output one should see

λ> :load "hello.hs"
[1 of 1] Compiling Main             ( hello.hs, interpreted )
Ok, one module loaded.
λ> :main
Hello World!

Reload a Loaded File

To reload a previously loaded file after you make changes to the file, run :reload.

How To Cite

Zelko, Jacob. Notes on Programming in Haskell. https://jacobzelko.com/11032021155827-haskell-programming. November 3 2021.

References:

Discussion:

CC BY-SA 4.0 Jacob Zelko. Last modified: November 24, 2023. Website built with Franklin.jl and the Julia programming language.