CompSci 220. Programming Methodology 16: Understanding FP Error Handling Part 2

Similar documents
You ve encountered other ways of signalling errors. For example, if you lookup an unbound key in a hashtable, Java (and Scala) produce nulls:

Chapter 11 Exception Handling

CompSci 220. Programming Methodology 12: Functional Data Structures

Strings are not collections, but they behave like them in almost every way. For example,

Chapter 15. Functional Programming Languages

Comp 311 Functional Programming. Eric Allen, Two Sigma Investments Robert Corky Cartwright, Rice University Sagnak Tasirlar, Two Sigma Investments

More about Binary 9/6/2016

CPS 506 Comparative Programming Languages. Programming Language Paradigm

CS1 Lecture 3 Jan. 18, 2019

CS1 Lecture 3 Jan. 22, 2018

Computation Abstraction Going beyond programming language glue, or what we've missed from FP for so long in mainstream

COMPUTER SCIENCE TRIPOS

The SCAlable LAnguage

Programming Principles

Checking Multiple Conditions

Exercise 1: Graph coloring (10 points)

learning objectives learn about variables, their types and their values learn about different number representations

OCaml Data CMSC 330: Organization of Programming Languages. User Defined Types. Variation: Shapes in Java

Programming Paradigms

Getting Started. Office Hours. CSE 231, Rich Enbody. After class By appointment send an . Michigan State University CSE 231, Fall 2013

Soda Machine Laboratory

Practically Functional. Daniel Spiewak

Announcements. CSCI 334: Principles of Programming Languages. Lecture 16: Intro to Scala. Announcements. Squeak demo. Instructor: Dan Barowy

Example Scheme Function: equal

QUIZ. What is wrong with this code that uses default arguments?

age = 23 age = age + 1 data types Integers Floating-point numbers Strings Booleans loosely typed age = In my 20s

A Third Look At ML. Chapter Nine Modern Programming Languages, 2nd ed. 1

Optimizing Higher-Order Functions in Scala

CS 115 Lecture 4. More Python; testing software. Neil Moore

Functional Programming. Pure Functional Languages

Standard ML. Curried Functions. ML Curried Functions.1

Implementing Joins using Extensible Pattern Matching

The University of Melbourne Department of Computer Science and Software Engineering Software Design Semester 2, 2003

CMSC 201 Fall 2016 Lab 09 Advanced Debugging

CS 360: Programming Languages Lecture 12: More Haskell

CSCI 1101B. Boolean Expressions

Python and Bioinformatics. Pierre Parutto

5. Selection: If and Switch Controls

Monadologie. professional help for type anxiety. Christopher League 12 July 2010

Scala. Fernando Medeiros Tomás Paim

As stated earlier, the declaration

Exception Handling. Genome 559

CS1622. Semantic Analysis. The Compiler So Far. Lecture 15 Semantic Analysis. How to build symbol tables How to use them to find

Finally, all fields are public by default, so you can easily write simple functions, such as this one, without writing getters:

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

Linearizability Testing Manual

CSE 12 Abstract Syntax Trees

INF 212 ANALYSIS OF PROG. LANGS FUNCTION COMPOSITION. Instructors: Crista Lopes Copyright Instructors.

The Big Python Guide

Homework 7: Sudoku. Preliminaries. Overview

GIS 4653/5653: Spatial Programming and GIS. More Python: Statements, Types, Functions, Modules, Classes

CSC Java Programming, Fall Java Data Types and Control Constructs

Compiling expressions

Pointers in C/C++ 1 Memory Addresses 2

CSE 331 Midterm Exam Sample Solution 2/13/12

Notes from a Short Introductory Lecture on Scala (Based on Programming in Scala, 2nd Ed.)

CS61B Lecture #14: Integers. Last modified: Wed Sep 27 15:44: CS61B: Lecture #14 1

EECS 183. Week 3 - Diana Gage. www-personal.umich.edu/ ~drgage

Basics of Java: Expressions & Statements. Nathaniel Osgood CMPT 858 February 15, 2011

7. (2 pts) str( str( b ) ) str '4' will not compile (single, double, or triple quotes

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

15 150: Principles of Functional Programming. More about Higher-Order Functions

Topic 13: Packages and Imports

GADTs. Wouter Swierstra and Alejandro Serrano. Advanced functional programming - Lecture 7. [Faculty of Science Information and Computing Sciences]

20 Subclassing and Mutation

CS 1301 Exam 1 Spring 2014

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

Typed Lambda Calculus and Exception Handling

GADTs. Alejandro Serrano. AFP Summer School. [Faculty of Science Information and Computing Sciences]

Metaprogramming assignment 3

Problem 1: Binary Trees: Flatten

Using Scala in CS241

Designing Robust Classes

i219 Software Design Methodology 7. Information hiding and reuse Kazuhiro Ogata (JAIST) Outline of lecture

Exceptions and Continuations. Lecture #19: More Special Effects Exceptions and OOP. Approach II: Non-Standard Return. Approach I: Do Nothing

Lab 10: Sockets 12:00 PM, Apr 4, 2018

Exceptions Programming 1 C# Programming. Rob Miles

Exceptions. Exceptions. Exceptional Circumstances 11/25/2013

Lecture 2. 1 Immutability. 2 Case Classes

Lecture 4 CSE July 1992

CS52 - Assignment 8. Due Friday 4/15 at 5:00pm.

1.3.4 case and case* macro since 1.2. Listing Conditional Branching, Fast Switch. Listing Contract

Functional programming

CS558 Programming Languages

Chapter 1. Fundamentals of Higher Order Programming

Parsing Scheme (+ (* 2 3) 1) * 1

Fundamentals of Object Oriented Programming

INF 102 CONCEPTS OF PROG. LANGS FUNCTIONAL COMPOSITION. Instructors: James Jones Copyright Instructors.

CS 360: Programming Languages Lecture 10: Introduction to Haskell

CPL 2016, week 10. Clojure functional core. Oleg Batrashev. April 11, Institute of Computer Science, Tartu, Estonia

AP Computer Science Unit 1. Programs

Introduction to Programming Using Java (98-388)

Patterns The Essence of Functional Programming

UMBC CMSC 331 Final Exam

Topic 6: Exceptions. Exceptions are a Java mechanism for dealing with errors & unusual situations

6.184 Lecture 4. Interpretation. Tweaked by Ben Vandiver Compiled by Mike Phillips Original material by Eric Grimson

THE INTEGER DATA TYPES. Laura Marik Spring 2012 C++ Course Notes (Provided by Jason Minski)

Note that pcall can be implemented using futures. That is, instead of. we can use

EECS 700 Functional Programming

Arrays in C++ Instructor: Andy Abreu

Transcription:

CompSci 220 Programming Methodology 16: Understanding FP Error Handling Part 2

Objectives Option Composition and Lifting For- Comprehension Expansion The Either Data Type Option and Either in the Standard Library

Examples Let us first take a look at some more examples of using Option.

Option Composition and Lifting How does Option affect existing code? You may have been concerned that Option will infect an entire code base one can imagine how any callers of methods that take or return Option will need to be modified to handle either Some or None. Fortunately, this does not happen. We can lift ordinary functions to become functions that operate on Option.

Problem Example Consider the math.abs function on Double: math.abs(v: Double): Double What if we wanted to pass an Option to math.abs or pass the result of the result of math.abs to a function to another function that expects an Option[Double]? We could pattern match on Option and extract the value before calling math.abs. Or, we could wrap the result in Some. But, there is a better way

Lifting to Option Here is an example of what we want to do: val abso: Option[Double] => Option[Double] = lift(math.abs) Here is the type signature of lift: def lift[a,b](f: A => B): Option[A] => Option[B] =??? Take out a piece of paper and write out the implementation of lift. You should use a functional method from the Option type to do this.

Lifting to Option Here is an example of what we want to do: val abso: Option[Double] => Option[Double] = lift(math.abs) Here is the type signature of lift: def lift[a,b](f: A => B): Option[A] => Option[B] = _ map f See how this works?

Lifting to Option Here is an example of what we want to do: val abso: Option[Double] => Option[Double] = lift(math.abs) Here is the type signature of lift: def lift[a,b](f: A => B): Option[A] => Option[B] = _ map f See how this works? We return a new function by using the _ anonymous function syntax

Lifting to Option Here is an example of what we want to do: val abso: Option[Double] => Option[Double] = lift(math.abs) Here is the type signature of lift: def lift[a,b](f: A => B): Option[A] => Option[B] = _ map f See how this works? This maps the first option using function f that is provided to lift.

Lift Design Pattern? What design pattern does the lift function implement?

Lift Design Pattern? What design pattern does the lift function implement?

Options and Exceptions Imagine you are implementing the logic for a car insurance company s website, which contains a page where users can submit a form to request an instance online quote.

Options and Exceptions Imagine you are implementing the logic for a car insurance company s website, which contains a page where users can submit a form to request an instance online quote. We would like to parse the information from this form and ultimately call our rate function.

Rate Function def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double We want to be able to call this function, but if the user is submitting their age and number of speeding tickets in a web form, these fields will arrive as simple strings that we have to (try to) parse into integers.

Rate Function age = 42 parse def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double We want to be able to call this function, but if the user is submitting their age and number of speeding tickets in a web form, these fields will arrive as simple strings that we have to (try to) parse into integers.

Rate Function age = 42 tickets = three parse parse EXCEPTION! def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double We want to be able to call this function, but if the user is submitting their age and number of speeding tickets in a web form, these fields will arrive as simple strings that we have to (try to) parse into integers.

Rate Function age = 42 tickets = three parse parse EXCEPTION! def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double So, what if parse throws an exception? 42.toInt is ok, but three.tointthrows a NumberFormatException! This does not fit well into our functional model. We need a way to convert an Exception into an Option.

Exceptions to Options Ideally, we want to be able to do something like this: Try { 42.toInt } // Try { } should evaluate to Option Have we seen a way to do this before? What language technique can we use to implement this?

Implementing Try Here is the signature: def Try[A](block: => A): Option[A] Spend a few minutes to see if you can implement this. The given block could possibly throw an exception.

Implementing Try Here is the signature: def Try[A](block: => A): Option[A] = try Some(a) catch { case e: Exception => None } Spend a few minutes to see if you can implement this. The given block could possibly throw an exception.

Implement parseinsuranceratequote Ok, so now we can convert exceptions into Options. Let us implement a function to parse strings into ints from our insurance website and call insuranceratequote. Try it! def parseinsuranceratequote(age: String, numberofspeedingtickets: String): Option[Double] =??? def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double

Implement parseinsuranceratequote That wasn t so hard. But, we have a problem. def parseinsuranceratequote(age: String, numberofspeedingtickets: String): Option[Double] =??? val optage = Try { age.toint } val opttickets = Try { numberofspeedingtickets.toint } insuranceratequote(optage, opttickets) } def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double

Implement parseinsuranceratequote That wasn t so hard. But, we have a problem. It doesn t compile! def parseinsuranceratequote(age: String, numberofspeedingtickets: String): Option[Double] =??? val optage = Try { age.toint } val opttickets = Try { numberofspeedingtickets.toint } insuranceratequote(optage, opttickets) } def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double

Implement parseinsuranceratequote It doesn t compile because there is a type error. insuranceratequoteexpects Ints, but we are giving it Options. How do we solve this one? def parseinsuranceratequote(age: String, numberofspeedingtickets: String): Option[Double] =??? val optage = Try { age.toint } val opttickets = Try { numberofspeedingtickets.toint } insuranceratequote(optage, opttickets) } def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double

Implement parseinsuranceratequote What we need is a function extracts the two Ints (age & tickets) from the Option values, plugs them in to the insuranceratequotefunction, and then returns an Option def parseinsuranceratequote(age: String, numberofspeedingtickets: String): Option[Double] =??? val optage = Try { age.toint } val opttickets = Try { numberofspeedingtickets.toint } insuranceratequote(optage, opttickets) } def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double

Implement map2 Write a generic function map2 that combines two Option values using a binary function. If either Option value is None, then the return value is too. Here is its signature: def map2[a,b,c](a: Option[A], b: Option[B])(f: (A,B) => C): Option[C] =???

Implement map2 Write a generic function map2 that combines two Option values using a binary function. If either Option value is None, then the return value is too. Here is its signature: def map2[a,b,c](a: Option[A], b: Option[B])(f: (A,B) => C): Option[C] = (a,b) match { case (Some(x), Some(y)) => Some(f(x,y)) case _ => None }

Implement map2 Write a generic function map2 that combines two Option values using a binary function. If either Option value is None, then the return value is too. Here is its signature: def map2[a,b,c](a: Option[A], b: Option[B])(f: (A,B) => C): Option[C] = for { x <- a y <- b } yield f(x,y)

Fixing The Problem: map2 What we need is a function extracts the two Ints (age & tickets) from the Option values, plugs them in to the insuranceratequotefunction, and then returns an Option def parseinsuranceratequote(age: String, numberofspeedingtickets: String): Option[Double] =??? val optage = Try { age.toint } val opttickets = Try { numberofspeedingtickets.toint } insuranceratequote(optage, opttickets) } def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double

Fixing The Problem: map2 What we need is a function extracts the two Ints (age & tickets) from the Option values, plugs them in to the insuranceratequotefunction, and then returns an Option def parseinsuranceratequote(age: String, numberofspeedingtickets: String): Option[Double] =??? val optage = Try { age.toint } val opttickets = Try { numberofspeedingtickets.toint } map2(optage, opttickets)(insuranceratequote) } def insuranceratequote(age: Int, numberofspeedingtickets: Int): Double

Either Data Type Option is great for many cases. However, what if you need to indicate the error that occurred? Option, just gives us None For that, we have the Either data type: sealed trait Either[+E, +A] case class Left[+E](value: E) extends case class Right[+A](value: A) extends Either[E,Nothing] Either[Nothing,A]

Revisiting the Mean Function with Either We had this definition for mean using Option: def mean(xs: Seq[Double]): Option[Double] = if (xs.isempty) None else Some(xs.sum / xs.length) We can easily convert this to use the Either type.

Revisiting the Mean Function with Either We had this definition for mean using Option: def mean(xs: Seq[Double]): Either[String,Double] = if (xs.isempty) Left( mean of empty list! ) else Right(xs.sum / xs.length)

Exceptions to Eithers Sometimes, we want to include more information about the error: def safediv(x: Int, y: Int): Either[Exception,Int] = try Right(x / y) catch { case e: Exception => Left(e) }

Exceptions to Eithers With Try Now, we can generalize this: def Try[A](a: => A): Either[Exception,A] = try Right(a) catch { case e: Exception => Left(e) }