Haskell: an introduction

20 downloads 137283 Views 2MB Size Report
Feb 5, 2013 ... Real World Haskell. Going further. IO: back to basics. Enter your name: >. Enter your name: > Dave Weckl ↲. Haskell: an introduction. 21 / 34.
Introduction

Real World Haskell

Going further

Haskell: an introduction Sylvain HENRY [email protected] University of Bordeaux - LaBRI - Inria

February 5th, 2013

Haskell: an introduction

1 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Outline

Introduction

Real World Haskell

Going further

Haskell: an introduction

2 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Outline

Introduction Real World Haskell Going further

Haskell: an introduction

3 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Haskell: an introduction

Real World Haskell

4 / 34

Going further

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Haskell

1. purely functional programming language 2. lazily evaluated 3. statically typed 4. elegant and concise

Haskell: an introduction

5 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Functional: functions f : x 7→ 10 + x g : x 7→ x × 2 f g h r

x x = =

= = f h

h=f ◦g r = h(10)

10 + x x ∗ 2 . g 10 k : (x, y) 7→ x + y r2 = k(10, 20)

k x y = x + y r 2 = k 10 20 f = k 10 −− c u r r y i n g Haskell: an introduction

6 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Functional: higher-order functions

g f x = ( f x) ∗ ( f ( f x)) square x = x ˆ 2 r = g square 2

−− r = 64

r = g ( \ x → x ∗2 + x ˆ 2 ) 2

−− r = 640

r = map ( ∗ 2 ) [ 1 , 2 , 3 ]

−− r = [ 2 , 4 , 6 ]

Haskell: an introduction

7 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Functional: pattern-matching −− L i s t s a r e [ 1 , 2 , 3 ] == 1 == 1 == 1

”cons− l i s t s ” : [2 ,3] : 2 : [3] : 2 : 3 : []

l e n g t h l i s t = case l i s t o f [] → 0 x : xs → 1 + ( length xs ) length [ ] = 0 length ( x : xs ) = 1 + ( length xs )

Haskell: an introduction

8 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Purely functional Properties I Immutable variables I

I

Referential transparency I

I

if a = 5, it is true for the entire scope f x always returns the same result for given f and x

No side effect I

IO...

Very good properties to I

reason about programs (program transformations, proofs. . . )

I

compose functions together to write complex programs

Haskell: an introduction

9 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Purely functional Properties I Immutable variables I

I

Referential transparency I

I

if a = 5, it is true for the entire scope f x always returns the same result for given f and x

No side effect I

IO...

Very good properties to I

reason about programs (program transformations, proofs. . . )

I

compose functions together to write complex programs

Haskell: an introduction

9 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Purely functional Properties I Immutable variables I

I

Referential transparency I

I

if a = 5, it is true for the entire scope f x always returns the same result for given f and x

No side effect I

IO...

Very good properties to I

reason about programs (program transformations, proofs. . . )

I

compose functions together to write complex programs

Haskell: an introduction

9 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Purely functional Properties I Immutable variables I

I

Referential transparency I

I

if a = 5, it is true for the entire scope f x always returns the same result for given f and x

No side effect I

IO...

Very good properties to I

reason about programs (program transformations, proofs. . . )

I

compose functions together to write complex programs

Haskell: an introduction

9 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Purely functional Properties I Immutable variables I

I

Referential transparency I

I

if a = 5, it is true for the entire scope f x always returns the same result for given f and x

No side effect I

IO...

Very good properties to I

reason about programs (program transformations, proofs. . . )

I

compose functions together to write complex programs

Haskell: an introduction

9 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Purely functional: what to compute vs how e.g. kxk =

q x12 + · · · + xn2

double norm ( i n t n , double ∗ x s ) { double s = 0 . 0 ; f o r ( i n t i =0; i l e t d o u b l e s = map ( ∗ 2 ) [ 1 , 2 . . ] g h c i > d o u b l e s ! ! 15 32 g h c i > : type d o u b l e s doubles : : [ Integer ] g h c i > : type ( d o u b l e s ! ! ) ( doubles ! ! ) : : Int → Integer I

ghci is the REPL (Read-Eval-Print-Loop) of GHC

I

Very useful to quickly test and check!

Haskell: an introduction

14 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Type checking

g h c i > "Test" + 10 No i n s t a n c e f o r (Num S t r i n g ) a r i s i n g from a u s e o f ‘+ ’ P o s s i b l e f i x : add an i n s t a n c e d e c l a r a t i o n f o r (Num S t r i n g ) I n t h e e x p r e s s i o n : "Test" + 10 I

Ok it works

Haskell: an introduction

15 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Elegant and Concise −− HsCat . hs main = i n t e r a c t i d −− H s L i n e C o u n t . hs main = i n t e r a c t ( p r i n t f "%d" . l e n g t h . l i n e s ) I

Compile with ”ghc XXX.hs”

$ . / HsCat < b e t t e r a v e s . t x t Pif Paf Pouf $ . / HsLineCount < b e t t e r a v e s . t x t 3 Haskell: an introduction

16 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Outline

Introduction Real World Haskell Going further

Haskell: an introduction

17 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Real World Haskell I I

Not only a calculator language You can have I I I I I

I

IO (files, GUI, networking. . . ) Random numbers Threads Bindings to C libraries ...

Examples I I I I

Haskell: an introduction

xmonad (tiling X window manager) ghc (Haskell compiler) darcs (git-like version control system) ...

18 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Haskell: an introduction

Real World Haskell

19 / 34

Going further

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: first try getLine : : String −− r e a d a l i n e on s t d i n putStrLn : : S t r i n g → ( ) −− w r i t e a l i n e on s t d o u t

main = l e t la s t N a m e = g e t L i n e i n l e t f i r s t N a m e = getLine in putStrLn ( "Hi" ++ f i r s t N a m e ++ l a s t N a m e ) I

Haskell is referentially transparent I

I

lastName = getLine = firstName

Haskell is lazily evaluated I I I

Haskell: an introduction

Is firstName or lastName evaluated first? What if we never use firstName or lastName? putStrLn does not return a result and will never be evaluated 20 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: first try getLine : : String −− r e a d a l i n e on s t d i n putStrLn : : S t r i n g → ( ) −− w r i t e a l i n e on s t d o u t

main = l e t la s t N a m e = g e t L i n e i n l e t f i r s t N a m e = getLine in putStrLn ( "Hi" ++ f i r s t N a m e ++ l a s t N a m e ) I

Haskell is referentially transparent I

I

lastName = getLine = firstName

Haskell is lazily evaluated I I I

Haskell: an introduction

Is firstName or lastName evaluated first? What if we never use firstName or lastName? putStrLn does not return a result and will never be evaluated 20 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: first try getLine : : String −− r e a d a l i n e on s t d i n putStrLn : : S t r i n g → ( ) −− w r i t e a l i n e on s t d o u t

main = l e t la s t N a m e = g e t L i n e i n l e t f i r s t N a m e = getLine in putStrLn ( "Hi" ++ f i r s t N a m e ++ l a s t N a m e ) I

Haskell is referentially transparent I

I

lastName = getLine = firstName

Haskell is lazily evaluated I I I

Haskell: an introduction

Is firstName or lastName evaluated first? What if we never use firstName or lastName? putStrLn does not return a result and will never be evaluated 20 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: back to basics

Enter your name: >

Haskell: an introduction

Enter your name: > Dave Weckl ↲

21 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: back to basics

Enter your name: >

Haskell: an introduction

getLine

21 / 34

Enter your name: > Dave Weckl ↲

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: back to basics

Enter your name: >

getLine

Enter your name: > Dave Weckl ↲

"Dave Weckl"

Haskell: an introduction

21 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: back to basics

Enter your name: >

getLine

Enter your name: > Dave Weckl ↲

"Dave Weckl"

getLine :: World →(World, String)

Haskell: an introduction

21 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: back to basics

Enter your name: > Dave Weckl ↲

putStrLn

Enter your name: > Dave Weckl ↲ Hi Dave Weckl

"Hi Dave Weckl"

Haskell: an introduction

21 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: back to basics

Enter your name: > Dave Weckl ↲

putStrLn

Enter your name: > Dave Weckl ↲ Hi Dave Weckl

"Hi Dave Weckl"

putStrLn :: String →World →(World, ())

Haskell: an introduction

21 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: explicit ”world” variables getLine : : World → ( World , S t r i n g ) putStrLn : : S t r i n g → World → ( World , ( ) )

world 2

world 1

initWorld >

getLine

> Steve ↲

getLine

"Steve"

> Steve ↲ > Gadd ↲

world 3 putStrLn

> Steve ↲ > Gadd ↲ Hi Steve Gadd

"Gadd" "Hi Steve Gadd"

main : : World → ( World , ( ) ) main i n i t W o r l d = l e t ( world1 , f i ) = getLine i n i t W o r l d in l e t ( world2 , l a ) = getLine world1 in putStrLn ( p r i n t f "Hi %s %s" f i l a ) w o r l d 2 Haskell: an introduction

22 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Issue: what if a ”world” variable is used several times? initWorld

world 1 getLine

>

> Steve ↲

main i n i t W o r l d = l e t ( w1 , f i ) = g e t L i n e i n i t W o r l d i n l e t ( w2 , l a ) = g e t L i n e i n i t W o r l d i n p u t S t r L n ( p r i n t f " Hi % s % s " f i l a ) w2

"Steve" world 2 getLine Enter your name: >

> Gadd ↲

"Gadd"

Two solutions (at least) I

Check that it is not the case (Clean’s uniqueness types)

I

No explicit ”world” variables: provide composition operators instead (Haskell’s monadic IO)

Haskell: an introduction

23 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Issue: what if a ”world” variable is used several times? initWorld

world 1 getLine

>

> Steve ↲

main i n i t W o r l d = l e t ( w1 , f i ) = g e t L i n e i n i t W o r l d i n l e t ( w2 , l a ) = g e t L i n e i n i t W o r l d i n p u t S t r L n ( p r i n t f " Hi % s % s " f i l a ) w2

"Steve" world 2 getLine Enter your name: >

> Gadd ↲

"Gadd"

Two solutions (at least) I

Check that it is not the case (Clean’s uniqueness types)

I

No explicit ”world” variables: provide composition operators instead (Haskell’s monadic IO)

Haskell: an introduction

23 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Issue: what if a ”world” variable is used several times? initWorld

world 1 getLine

>

> Steve ↲

main i n i t W o r l d = l e t ( w1 , f i ) = g e t L i n e i n i t W o r l d i n l e t ( w2 , l a ) = g e t L i n e i n i t W o r l d i n p u t S t r L n ( p r i n t f " Hi % s % s " f i l a ) w2

"Steve" world 2 getLine Enter your name: >

> Gadd ↲

"Gadd"

Two solutions (at least) I

Check that it is not the case (Clean’s uniqueness types)

I

No explicit ”world” variables: provide composition operators instead (Haskell’s monadic IO)

Haskell: an introduction

23 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: composition operators t y p e W = World −− C o m p o s i t i o n w h i c h u s e s r e t r i e v e d v a l u e (>>=) : : (W → (W, a ) ) → ( a → W → (W, b ) ) → (W → (W, b ) ) main = g e t L i n e >>= p u t S t r L n = g e t L i n e >>= ( \ i n p u t → p u t S t r L n i n p u t ) −− C o m p o s i t i o n l i k e i m p e r a t i v e ”; ” (>>) : : (W → (W, a ) ) → (W → (W, b ) ) → (W → (W, b ) ) main = p u t S t r L n " Hello " >> p u t S t r L n " World " = p u t S t r L n " Hello " >>= ( \dummy → p u t S t r L n " World " ) −− L i f t p u r e v a l u e r e t u r n : : a → W → (W, a ) main = r e t u r n " Ho " >>= ( \ s → p u t S t r L n s >> p u t S t r L n s )

Haskell: an introduction

24 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: composition operators sugarized t y p e IO a = World → ( World , a ) −− C o m p o s i t i o n w h i c h u s e s r e t r i e v e d v a l u e (>>=) : : IO a → ( a → IO b ) → IO b main = g e t L i n e >>= p u t S t r L n = g e t L i n e >>= ( \ i n p u t → p u t S t r L n i n p u t ) −− C o m p o s i t i o n l i k e i m p e r a t i v e (>>) : : IO a → IO b → IO b

”; ”

main = p u t S t r L n " Hello " >> p u t S t r L n " World " = p u t S t r L n " Hello " >>= ( \dummy → p u t S t r L n " World " ) −− L i f t p u r e v a l u e r e t u r n : : a → IO a main = r e t u r n " Ho " >>= ( \ s → p u t S t r L n s >> p u t S t r L n s )

Haskell: an introduction

25 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: working example using composition operators main : : IO ( ) main = putStrLn "First name:" >> g e t L i n e >>= \ f i r s t n a m e → putStrLn "Last name:" >> g e t L i n e >>= \ l a s t n a m e → r e t u r n ( h i f i r s t n a m e l a s t n a m e ) >>= \ s → putStrLn s hi : : String → String → String h i f i l a = p r i n t f " Hello %s %s" f i l a

Haskell: an introduction

26 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

IO: working example using do-notation main : : IO ( ) main = do putStrLn "First name:" f i r s t n a m e ← getLine putStrLn "Last name:" lastname ← getLine let s = hi firstname lastname putStrLn s hi : : String → String → String h i f i l a = p r i n t f " Hello %s %s" f i l a

Haskell: an introduction

27 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Simon L. Peyton Jones and Philip Wadler. Imperative functional programming. In Proceedings of the 20th ACM SIGPLAN-SIGACT symposium on Principles of programming languages, POPL ’93, pages 71–84, New York, NY, USA, 1993. ACM.

Haskell: an introduction

28 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Outline

Introduction Real World Haskell Going further

Haskell: an introduction

29 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Haskell: an introduction

Real World Haskell

30 / 34

Going further

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Haskell Awesomeness 1/2 I

List-Comprehensions: I

e.g. r = {x + y , x ∈ xs, y ∈ ys, x ≥ 10, y > x}

r = [ x + y | x ← xs , y ← ys , x >= 1 0 , y > x ] I

QuickCheck

> q u i c k C h e c k ( ( \ s → r e v e r s e s == s ) : : S t r i n g → Bool ) ∗∗∗ F a i l e d ! F a l s i f i a b l e ( a f t e r 3 t e s t s and 2 s h r i n k s ) : " ab " > q u i c k C h e c k ( ( \ s → ( r e v e r s e ( r e v e r s e s ) == s ) : : Bool ) +++ OK, p a s s e d 100 t e s t s .

Haskell: an introduction

31 / 34

String →

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Haskell Awesomeness 2/2 I

Parallelism

a ← async ( f x y ) b ← async ( g w t ) r ← waitAny [ a , b ] I

Software Transactional Memory (STM)

t r a n s f e r n a c c o u n t 1 a c c o u n t 2 = a t o m i c a l l y $ do x ← readTVar a c c o u n t 1 when ( x < n ) r e t r y writeTVar account1 ( x − n) y ← readTVar a c c o u n t 2 writeTVar account2 ( y + n) Haskell: an introduction

32 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Haskell Awesomeness 3/2 I

Haskell language I I

I

Committee driven Fully specified

Glasgow Haskell Compiler (GHC) I I I

BSD license Actively developed Generate native code I I

I I

I

Optional LLVM backend C bindings easy to write and use

Optimizing compiler hlint: ”checkstyle”-like for Haskell

Community I I

Haskell: an introduction

#haskell, mailing-lists, wiki, papers Hackage: 4500+ packages

33 / 34

University of Bordeaux - LaBRI - Inria

Introduction

Real World Haskell

Going further

Questions?

Haskell: an introduction

34 / 34

University of Bordeaux - LaBRI - Inria