CS 360: Programming Languages Lecture 10: Introduction to Haskell

Similar documents
CS 360: Programming Languages Lecture 12: More Haskell

Haske k ll An introduction to Functional functional programming using Haskell Purely Lazy Example: QuickSort in Java Example: QuickSort in Haskell

An introduction introduction to functional functional programming programming using usin Haskell

CS 320: Concepts of Programming Languages

CS 457/557: Functional Languages

CS 11 Haskell track: lecture 1

The List Datatype. CSc 372. Comparative Programming Languages. 6 : Haskell Lists. Department of Computer Science University of Arizona

Solution sheet 1. Introduction. Exercise 1 - Types of values. Exercise 2 - Constructors

FUNCTIONAL PROGRAMMING 1 HASKELL BASICS

Practical Haskell. An introduction to functional programming. July 21, Practical Haskell. Juan Pedro Villa-Isaza. Introduction.

Introduction to Haskell

Haskell 101. (Version 1 (July 18, 2012)) Juan Pedro Villa Isaza

Programming Languages Fall 2013

This example highlights the difference between imperative and functional programming. The imperative programming solution is based on an accumulator

Intro. Scheme Basics. scm> 5 5. scm>

Programming Paradigms

Haskell Introduction Lists Other Structures Data Structures. Haskell Introduction. Mark Snyder

An introduction to functional programming. July 23, 2010

CSc 372. Comparative Programming Languages. 8 : Haskell Function Examples. Department of Computer Science University of Arizona

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

CS 440: Programming Languages and Translators, Spring 2019 Mon

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

A general introduction to Functional Programming using Haskell

SML A F unctional Functional Language Language Lecture 19

Thoughts on Assignment 4 Haskell: Flow of Control

Lecture 19: Functions, Types and Data Structures in Haskell

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

CS 320 Homework One Due 2/5 11:59pm

CSc 372 Comparative Programming Languages

CSC312 Principles of Programming Languages : Functional Programming Language. Copyright 2006 The McGraw-Hill Companies, Inc.

Introduction to Typed Racket. The plan: Racket Crash Course Typed Racket and PL Racket Differences with the text Some PL Racket Examples

Programming Paradigms and Languages Introduction to Haskell. dr Robert Kowalczyk WMiI UŁ

Scheme: Data. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Monday, April 3, Glenn G.

CS 320: Concepts of Programming Languages

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

Haskell: Lists. CS F331 Programming Languages CSCE A331 Programming Language Concepts Lecture Slides Friday, February 24, Glenn G.

CMSC 330: Organization of Programming Languages

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

CS Lecture 5: Pattern Matching. Prof. Clarkson Fall Today s music: Puff, the Magic Dragon by Peter, Paul & Mary

CSE413: Programming Languages and Implementation Racket structs Implementing languages with interpreters Implementing closures

Intro to Haskell Notes: Part 5

Informatics 1 Functional Programming Lectures 13 and 14 Monday 11 and Tuesday 12 November Type Classes. Don Sannella University of Edinburgh

Haskell Syntax in Functions

Informatics 1 Functional Programming Lecture 4. Lists and Recursion. Don Sannella University of Edinburgh

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Haskell Functions

n n Try tutorial on front page to get started! n spring13/ n Stack Overflow!

Functional Programming in Haskell for A level teachers

CMSC 330: Organization of Programming Languages. OCaml Data Types

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

Intro to Haskell Notes: Part 1

Functional Programming Lecture 1: Introduction

Haskell Scripts. Yan Huang

Abstract Types, Algebraic Types, and Type Classes

SCHEME AND CALCULATOR 5b

CSc 372 Comparative Programming Languages. 4 : Haskell Basics

Programming Paradigms

Logical Methods in... using Haskell Getting Started

Haskell Making Our Own Types and Typeclasses

Principles of Programming Languages

COSE212: Programming Languages. Lecture 3 Functional Programming in OCaml

Typed Racket: Racket with Static Types

CS1 Lecture 3 Jan. 18, 2019

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

Macros & Streams Spring 2018 Discussion 9: April 11, Macros

CSE 413 Languages & Implementation. Hal Perkins Winter 2019 Structs, Implementing Languages (credits: Dan Grossman, CSE 341)

Recursion and Induction: Haskell; Primitive Data Types; Writing Function Definitions

CMSC 330: Organization of Programming Languages. Functional Programming with Lists

Haskell Programs. Haskell Fundamentals. What are Types? Some Very Basic Types. Types are very important in Haskell:

Advanced Topics in Programming Languages Lecture 2 - Introduction to Haskell

PROGRAMMING IN HASKELL. Chapter 2 - First Steps

CSc 372. Comparative Programming Languages. 4 : Haskell Basics. Department of Computer Science University of Arizona

Shell CSCE 314 TAMU. Haskell Functions

Functional Programming. Pure Functional Programming

Quiz 3; Tuesday, January 27; 5 minutes; 5 points [Solutions follow on next page]

Scheme Tutorial. Introduction. The Structure of Scheme Programs. Syntax

COMP 105 Homework: Type Systems

Informatics 1 Functional Programming Lecture 9. Algebraic Data Types. Don Sannella University of Edinburgh

Introduction to Programming, Aug-Dec 2006

The Typed Racket Guide

CSE 3302 Programming Languages Lecture 8: Functional Programming

Functional Programming and Haskell

According to Larry Wall (designer of PERL): a language by geniuses! for geniuses. Lecture 7: Haskell. Haskell 98. Haskell (cont) - Type-safe!

Functional Programming for Logicians - Lecture 1

CS 360 Programming Languages Interpreters

Parsing. Zhenjiang Hu. May 31, June 7, June 14, All Right Reserved. National Institute of Informatics

CS457/557 Functional Languages

CIS 194: Homework 4. Due Wednesday, February 18, What is a Number?

It is better to have 100 functions operate one one data structure, than 10 functions on 10 data structures. A. Perlis

List Functions, and Higher-Order Functions

CS 360: Programming Languages Lecture 10: Logic Programming with Prolog

SMURF Language Reference Manual Serial MUsic Represented as Functions

Documentation for LISP in BASIC

CS1 Lecture 3 Jan. 22, 2018

Chapter 1. Fundamentals of Higher Order Programming

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Winter 2013

Haskell 98 in short! CPSC 449 Principles of Programming Languages

Applicative, traversable, foldable

Background Operators (1E) Young Won Lim 7/7/18

TOPIC 2 INTRODUCTION TO JAVA AND DR JAVA

Two Types of Types. Primitive Types in Java. Using Primitive Variables. Class #07: Java Primitives. Integer types.

Transcription:

CS 360: Programming Languages Lecture 10: Introduction to Haskell Geoffrey Mainland Drexel University Thursday, February 5, 2015 Adapted from Brent Yorgey s course Introduction to Haskell.

Section 1 Administrivia

Administrivia Homework 4 due Monday night. Midterm in class Tuesday. Homework 5 (Haskell) will be posted before the weekend. It will be due February 16. The course home page has instructions for getting GHC, the Haskell implementation we will be using, up and running on tux. I highly recommend reading Learn you a Haskell for Great Good! We will be covering many concepts very quickly in the next two lectures, and it will be extremely difficult for you to understand all the material if you don t complete the accompanying readings.

Section 2 Homework 3 Solutions

Section 3 Introduction to Haskell

Haskell Haskell is: Functional: function are first-class, and the meaning of a Haskell program is determined by evaluating functions rather than executing instructions. Pure: calling a function with the same arguments results in the same result every time. Lazy: expressions are not evaluated until their values are actually needed. Statically typed: every Haskell expression has a type, and types are checked at compile time.

Types Types are invariants: they state something that is true for all executions of a program. Types are statically checked. If a function uses, for example, a string as an integer, the error will be reported at compile time, not at run time. Up side: compiler catches errors for you. Down side: can t sneak errors past the compiler, error messages can be hard to decipher. Types serve as a form of documentation. Given just a type, you know a lot about how a function can be used and what it might do. Types help clarify your thinking about a program and its structure.

Abstraction in Haskell Each significant piece of functionality in a program should be implemented in just one place in the source code. Where similar functions are carried out by distinct pieces of code, it is generally beneficial to combine them into one by abstracting out the varying parts. Benjamin Pierce [Pie02] Functional languages, and in particular Haskell, are very good at abstraction. We have already seen higher-order functions, like map, filter, and fold, that capture reusable patterns we have repeatedly programmed by hand many times (what pattern is this?). Haskell s type classes add another powerful form of abstraction.

Wholemeal Programming Functional languages excel at wholemeal programming, a term coined by Geraint Jones. Wholemeal programming means to think big: work with an entire list, rather than a sequence of elements; develop a solution space, rather than an individual solution; imagine a graph, rather than a single path. The wholemeal approach often offers new insights or provides new perspectives on a given problem. It is nicely complemented by the idea of projective programming: first solve a more general problem, then extract the interesting bits and pieces by transforming the general program into more specialised ones. Ralph Hinze [Hin09] Consider The following C function: int sum_of_squares(int* arr, int len) { int acc = 0; for (int i = 0; i < len; i++ ) acc = acc + arr[i] * arr[i]; return acc; } This function has to worry about the low-level details of maintaining an index into the array. It also mixes up the details of what is really two separate operations: squaring numbers and summing them. We can write this function in Haskell as: sumofsquares xs = sum (map (^ 2) xs)

Learning Haskell Haskell is a challenging language to learn because it requires you to think differently about programming. Fortunately you now know Scheme, which gives you a head start Please do the readings from Learn You a Haskell. They will help!

Declarations and variables x :: Int x = 1 This fragment defines a variable x with the value 1. It also provides a type signature for x. The symbol :: is pronounced has type. The value of x cannot be changed! There is no set! in Haskell.

Using ghci The interpreter we will be using is ghci. It is actually part of the GHC compiler. Please check the course home page for a short guide to using GHC and ghci. Unfortunately the version installed on tux is broken the guide provides instructions for using our (not broken) version of GHC. Like mit-scheme, ghci provides a read-eval-print loop (REPL). Unlike mit-scheme, ghci lets you edit what you enter... Import ghci commands include :load, :reload, and :type.

Other types n :: Integer n = 93326215443944152681699238856266700490715968264381621468592963895217 pi :: Double pi = 3.141592653589793 singleprecisionpi :: Float singleprecisionpi = 3.141592653589793 b :: Bool b = True c1 :: Char c1 = x s1, :: String s1 = "Hello, world!" Haskell includes types for arbitrary-precision integers, floating-point numbers, Booleans, Unicode characters, and Unicode strings.

Boolean logic Boolean values can be combined with && (logical and), (logical or), and not. ex1 = True && False ex2 = not (False True) Values can be compared for equality with == and /=, or compared for order using <, >, <=, and >=. ex3 = ( a == a ) ex4 = (16 /= 3) ex5 = (5 > 3) && ( p <= q ) ex6 = "Haskell" > "Scheme" Haskell also has if expressions, but they are not used often guards and patterns, which we will see shortly, are preferred. ex7 = if "Haskell" > "Scheme" then "Haskell is better!" else "Scheme is better!"

Arithmetic ex7 = 3 + 2 ex8 = 19-27 ex9 = 2.35 * 8.6 ex10 = 8.7 / 3.1 ex11 = mod 19 3 ex12 = 19 mod 3 ex13 = 7 ^ 222 ex15 = (-3) * (-7) Backticks make a function name into an infix operator. Negative numbers must often be surrounded by parentheses to avoid having the negation sign parsed as subtraction. (Yes, this is ugly).

Division i :: Int i = 10 Division is slightly tricky. Trying to evaluate i / 2 will give us an error. Instead, we must write i div 2. div is for integral types, and / is for floating-point types.

Defining functions Recall the fact function we defined in Scheme. (define (fact n) (cond ((= n 0) 1) (else (* n (fact (- n 1)))))) We can define the same function as follows in Haskell. fact :: Integer -> Integer fact n = if n == 0 then 1 else n * fact (n-1) Remember when we said if is not often used? Here s the same function without if. fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

Functions in Haskell fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1) Note that we have given our function a type signature. This type says fact is a function from Integers to Integers. Each clause of fact is checked from top to bottom, and the first matching clause is chosen. This is an example of Haskell s pattern matching capabilities. We will see much more of this later.

Guards Choices can also be made based on arbitrary Boolean expressions using guards. fact :: Integer -> Integer fact n n == 0 = 1 otherwise = n * fact (n-1) Guards are always Boolean expressions. Question: What do you think otherwise evaluates to? Any number of guards can be associate with each clause. A clause s guards are checked from top to bottom, and the first one that evaluates to True is chosen. If no guard evaluates to True, matching continues with the next clause.

Function with multiple arguments Functions may take multiple arguments, like this add3 :: Int -> Int -> Int add3 x y z = x + y + z ex16 = add3 1 The syntax for the type of a function with multiple arguments is t1 -> t2 ->... -> tn -> result. We can partially apply the function add3 to a value, as we did when we defined ex16. Question: What do you think the type of ex16 is? Another question: How could you figure it out if you don t know the answer? Note than function application has higher precedence than any infix operator. Thus add 1 n+1 3 parses as (add3 1 n) + (1 3). Instead, write add3 1 (n+1) 3.

Lists Like Scheme, lists are one of the most basic types Haskell provides. nums, range, range2 :: [Integer] nums = [1,2,3,19] range = [1..100] range2 = [2,4..100] Like Python, Haskell has list comprehensions. Strings are lists of characters String is just an abbreviation for [Char]. hello1 :: [Char] hello1 = [ h, e, l, l, o ] hello2 :: String hello2 = "hello" hellosame = hello1 == hello2 -- Evaluates to True!

Constructing Lists The simplest list is the empty list: nil = [] Haskell has cons, but it is an infix operator, and it s name is :. We can build lists using : or by using special list notation. ex17 = 1 : [] ex18 = 3 : (1 : []) ex19 = 2 : 3 : 4 : [] ex20 = [2,3,4] == 2 : 3 : 4 : [] -- Also evaluates to True Let s write some functions on lists...

Haskell vs. Scheme: append In Scheme... (define (append xs ys) (if (null? xs) ys (cons (car xs) (append (cdr xs) ys)))) And in Haskell... append xs ys = if null xs then ys else head xs : append (tail xs) ys And in Haskell again... append [] ys = ys append (x:xs) ys = x : append xs ys What is the type of append? Let s give it a type signature that says

Making a mistake in append Let s try this variation on append: append :: [Int] -> [Int] -> [Int] append [] ys = ys append (x:xs) ys = xs : append xs ys Is this variation correct? What happens if we make the analogous mistake in the Scheme version of append? What do you think happens if we give ghci this definition?

GHC Errors... lecture10-examples.hs:6:20: Couldn t match expected type Int with actual type [Int] In the first argument of (:), namely xs In the expression: xs : append xs ys Failed, modules loaded: none. Prelude> Don t be scared of errors. First we are told Couldn t match expected type Int with actual type Int. This means that something was expected to have a Int, but actually had type [Int]. What something? The next line tells us: it s the first argument of (:) which is at fault, namely, xs. The next lines go on to give us a bit more context. You might not understand all of an error message, but you will learn a lot by reading it!

Algebraic Data Types Let s see how the Bool type is defined in the standard library: data Bool = True False data mean we are introducing a new data type. The part before the = is the name of the type we are defining. The parts after the = are the data constructors. They specify the different values this type can have, and they are separated by a vertical bar,.

Defining a data type for shapes We can define a new data type that represents shapes as follows. data Shape = Circle Double Double Double Rectangle Double Double Double Double The Circle data constructor has three fields: the coordinates of its center, and its radius. The Rectangle data constructor has four fields: the coordinates of its upper-left and lower-right corner. We can also define a function that calculate the area of a shape. data type that represents shapes as follows. area :: Shape -> Double area (Circle r) = pi * r ^ 2 area (Rectangle x1 y1 x2 y2) = abs (x2 - x1) * abs (y2 - y1)

Algebraic Data Types in General In general, an algebraic data type has one or more data constructors. Each data constructor can have zero or more arguments. Type and data constructor names must always start with a capital letter. Variables, including names of functions, must always start with a lowercase letter.

Pattern Matching area :: Shape -> Double area (Circle r) = pi * r ^ 2 area (Rectangle x1 y1 x2 y2) = abs (x2 - x1) * abs (y2 - y1) We ve already seen examples of pattern matching, but let s see how it works in general. Fundamentally, pattern matching is about taking apart a value by finding out which constructor it was built with. Notice how in our definition of area, names are given to the values that are associate with the data constructor. An underscore, _, is a wildcard pattern that matches anything. A pattern of the form v@pat can be used to match a value against the pattern pat while also binding the variable v to the entire value being matched. For example: firstcircle :: [Shape] -> Shape firstcircle [] = error "Urk!" firstcircle (shape@(circle _) : _) = shape firstcircle (_:shapes) = firstcircle shapes Patterns can also be nested, as in firstcircle.

Pattern Matching Syntax The general syntax for pattern matching is: pat ::= _ var var @ pat (Constructor pat 1 pat 2... pat n )

Case Expressions The fundamental Haskell construct for pattern matching is the case expression. In general, a case expression looks like this: case exp of pat1 -> exp1 pat2 -> exp2... In fact, the multi-clause syntax for defining functions that we have seen is just syntactic sugar for a case expression. Instead of this area :: Shape -> Double area (Circle r) = pi * r ^ 2 area (Rectangle x1 y1 x2 y2) = abs (x2 - x1) * abs (y2 - y1) we could have written this area :: Shape -> Double area shape = case shape of (Circle r) -> pi * r ^ 2 (Rectangle x1 y1 x2 y2) -> abs (x2 - x1) * abs (y2 - y1)

Tuples There is one more pervasive data type we haven t mentioned: tuples. Tuples have a single data constructor and can have any number of values associated with this data constructor. There is also special syntax for tuples. anintpair :: (Int, Int) anintpair = (3, 4)

Records It is often convenient to refer to field of a data constructor by name. radius :: Shape -> Double radius (Circle r) = r radius (Rectangle ) = error "urk!" Haskell provides syntax for defining and matching on records. data Shape = Circle { centx :: Double, centy :: Double, radius :: Double} Rectangle { ulx :: Double, uly :: Double, urx :: Double, ury :: Double } mycircle = Circle 0 0 1 myothercircle = Circle { centx = 0, centy = 0, radius = 1 } radiusof circle = radius circle area (Circle { radius = r }) = pi * r ^ 2 area (Rectangle { ulx = x1, uly = y1, urx = x2, ury = y2 }) = abs (x2 - x1) * abs (y2 - y1)

Section 4 References

References [Hin09] Ralf Hinze. Functional pearl: La Tour D Hanoï. In Proceedings of the 14th ACM SIGPLAN International Conference on Functional Programming (ICFP 09), pages 3 10, New York, NY, USA, 2009. [Pie02] Benjamin C. Pierce. Types and Programming Languages. Cambridge, Mass, feb 2002.