Example: A Compiler Fragment (1) Example: A Compiler Fragment (2) Example: A Compiler Fragment (3)

Similar documents
Monads in Haskell. Nathanael Schilling. December 12, 2014

Introduction to Functional Programming in Haskell 1 / 56

Applicative, traversable, foldable

Haskell Overloading (1) LiU-FP2016: Lecture 8 Type Classes. Haskell Overloading (3) Haskell Overloading (2)

Programming Languages

Applicative, traversable, foldable

CSCE 314 Programming Languages Functors, Applicatives, and Monads

Haskell Monads CSC 131. Kim Bruce

Denotational Semantics. Domain Theory

CFRP issues: Restart (2)

Chapter 11 :: Functional Languages

Verified compilers. Guest lecture for Compiler Construction, Spring Magnus Myréen. Chalmers University of Technology

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

Monads and all that I. Monads. John Hughes Chalmers University/Quviq AB

Programming Languages Lecture 15: Recursive Types & Subtyping

G53CMP: Lecture 4. Syntactic Analysis: Parser Generators. Henrik Nilsson. University of Nottingham, UK. G53CMP: Lecture 4 p.1/32

Trees. Solution: type TreeF a t = BinF t a t LeafF 1 point for the right kind; 1 point per constructor.

FUNCTIONAL PEARLS The countdown problem

The essence of dataflow programming. Teooriapäevad Kokel 2,

Programming Languages Third Edition

Outline. What is semantics? Denotational semantics. Semantics of naming. What is semantics? 2 / 21

Monad Transformers Step by Step

Background Type Classes (1B) Young Won Lim 6/28/18

Reasoning About Imperative Programs. COS 441 Slides 10

Haskell in the corporate environment. Jeff Polakow October 17, 2008

Haskell: From Basic to Advanced. Part 2 Type Classes, Laziness, IO, Modules

CSc 372. Comparative Programming Languages. 2 : Functional Programming. Department of Computer Science University of Arizona

The First Monad Tutorial

Lecture C-10: Parser Combinators - Introduction

College Functors, Applicatives

Monads. Mark Hills 6 August Department of Computer Science University of Illinois at Urbana-Champaign

1 Delimited continuations in Haskell

Programming Language Pragmatics

Recap: Typical Compiler Structure. G53CMP: Lecture 2 A Complete (Albeit Small) Compiler. This Lecture (2) This Lecture (1)

A general introduction to Functional Programming using Haskell

JVM ByteCode Interpreter

Introduction to lambda calculus Part 3

Interleaving data and effects

A system of constructor classes: overloading and implicit higher-order polymorphism

(Refer Slide Time: 4:00)

Monads and all that III Applicative Functors. John Hughes Chalmers University/Quviq AB

LiU-FP2010 Part II: Lecture 7 Concurrency

Lazy State Evaluation of Process Functional Programs

Programming with Math and Logic

Value Recursion in Monadic Computations

Relation Overriding. Syntax and Semantics. Simple Semantic Domains. Operational Semantics

Intro to semantics; Small-step semantics Lecture 1 Tuesday, January 29, 2013

The essence of dataflow programming

CS 381: Programming Language Fundamentals

The Arrow Calculus (Functional Pearl)

MPRI course 2-4 Functional programming languages Exercises

More Lambda Calculus and Intro to Type Systems

Overview. Elements of Programming Languages. Evaluation order. Evaluation order

COMP3151/9151 Foundations of Concurrency Lecture 8

Accurate Step Counting

Functional Languages. CSE 307 Principles of Programming Languages Stony Brook University

Functional Languages. Hwansoo Han

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

Functional Programming. Pure Functional Programming

Program Calculus Calculational Programming

Idioms are oblivious, arrows are meticulous, monads are promiscuous

Type system. Type theory. Haskell type system. EDAN40: Functional Programming Types and Type Classes (revisited)

Advanced Programming Handout 7. Monads and Friends (SOE Chapter 18)

An introduction introduction to functional functional programming programming using usin Haskell

Monadic Augment and Generalised Short Cut Fusion

Modules Matter Most. Robert Harper Carnegie Mellon University. MacQueen Fest Chicago May 2012

Ornaments in ML. Thomas Williams, Didier Rémy. April 18, Inria - Gallium

CSC324 Principles of Programming Languages

Metaprogramming assignment 3

CS 320: Concepts of Programming Languages

9/23/2014. Why study? Lambda calculus. Church Rosser theorem Completeness of Lambda Calculus: Turing Complete

CATEGORIES AND COMPUTATION BRIEF MONAD EXAMPLE. Andrew R. Plummer. Department of Linguistics The Ohio State University.

Compiling Exceptions Correctly

M. Snyder, George Mason University LAMBDA CALCULUS. (untyped)

Haskell & functional programming, some slightly more advanced stuff. Matteo Pradella

Accurate Step Counting

Lists. Michael P. Fourman. February 2, 2010

Sémantique des Langages de Programmation (SemLP) DM : Region Types

CS The IO Monad. Slides from John Mitchell, K Fisher, and S. Peyton Jones

CS 242. Fundamentals. Reading: See last slide

INTRODUCTION TO FUNCTIONAL PROGRAMMING

Topics Covered Thus Far CMSC 330: Organization of Programming Languages

CA Compiler Construction

CE221 Programming in C++ Part 1 Introduction

Comprehending Monads. Philip Wadler. University of Glasgow. Abstract. Category theorists invented monads in the 1960's to concisely express certain

The University of Nottingham SCHOOL OF COMPUTER SCIENCE A LEVEL 2 MODULE, SPRING SEMESTER COMPILERS ANSWERS. Time allowed TWO hours

Variables and Operators 2/20/01 Lecture #

Data types à la carte. Wouter Swierstra Dutch HUG 25/8/10

CSCC24 Functional Programming Scheme Part 2

Programming Languages

Recap: Functions as first-class values

CMSC 330: Organization of Programming Languages

Software System Design and Implementation

Written Presentation: JoCaml, a Language for Concurrent Distributed and Mobile Programming

Foundations. Yu Zhang. Acknowledgement: modified from Stanford CS242

CSc 520 final exam Wednesday 13 December 2000 TIME = 2 hours

Exercise 1 (2+2+2 points)

COSC252: Programming Languages: Semantic Specification. Jeremy Bolton, PhD Adjunct Professor

Advanced Type System Features Tom Schrijvers. Leuven Haskell User Group

Introduction. chapter Functions

Transcription:

LiU-FP2016: Lecture 7 Monads Henrik Nilsson University of Nottingham, UK Example: A Compiler Fragment (1) Identification is the task of relating each applied identifier occurrence to its declaration or definition: public class C { int x, n; void set(int n) { x n; } } In the body of set, the one applied occurrence of x refers to the instance variablex n refers to the argumentn. Example: A Compiler Fragment (4) Goals of the identification phase: Annotate each applied identifier occurrence with attributes of the corresponding variable declaration. I.e., map unannotated ASTExp() to annotated ASTExpAttr. Report conflicting variable definitions and undefined variables. identification :: Exp () -> (Exp Attr, [ErrorMsg]) LiU-FP2016: Lecture 7 p.1/52 LiU-FP2016: Lecture 7 p.4/52 LiU-FP2016: Lecture 7 p.7/52 A Blessing and a Curse The BIG advantage of pure functional programming is everything is explicit; i.e., flow of data manifest, no side effects. Makes it a lot easier to understand large programs. The BIG problem with pure functional programming is everything is explicit. Can add a lot of clutter, make it hard to maintain code LiU-FP2016: Lecture 7 p.2/52 Example: A Compiler Fragment (2) Consider an ASTExp for a simple expression language.exp is a parameterized type: the type parameteraallows variables to be annotated with an attribute of typea. data Exp a LitInt Int Var Id a UnOpApp UnOp (Exp a) BinOpApp BinOp (Exp a) (Exp a) If (Exp a) (Exp a) (Exp a) Let [(Id, Type, Exp a)] (Exp a) LiU-FP2016: Lecture 7 p.5/52 Example: A Compiler Fragment (5) Example: Before Identification Let [("x", IntType, LitInt 7)] (BinOpApp Plus (Var "x" ()) (LitInt 35)) After identification: Let [("x", IntType, LitInt 7)] (BinOpApp Plus (Var "x" (1, IntType)) (LitInt 35)) LiU-FP2016: Lecture 7 p.8/52 Conundrum Shall I be pure or impure? (Wadler, 1992) Absence of effects - facilitates understanding and reasoning - makes lazy evaluation viable - allows choice of reduction order, e.g. parallel - enhances modularity and reuse. Effects (state, exceptions,... ) can - help making code concise - facilitate maintenance - improve the efficiency. Example: A Compiler Fragment (3) Example: The following code fragment let int x 7 in x + 35 would be represented like this (before identification): Let [("x", IntType, LitInt 7)] (BinOpApp Plus (Var "x" ()) (LitInt 35)) Example: A Compiler Fragment (6) entervar inserts a variable at the given scope level and of the given type into an environment. Check that no variable with same name has been defined at the same scope level. If not, the new variable is entered, and the resulting environment is returned. Otherwise an error message is returned. entervar :: Id -> Int -> Type -> Env -> Either Env ErrorMsg LiU-FP2016: Lecture 7 p.3/52 LiU-FP2016: Lecture 7 p.6/52 LiU-FP2016: Lecture 7 p.9/52

Example: A Compiler Fragment (7) Functions that do the real work: identaux :: Int -> Env -> Exp () -> (Exp Attr, [ErrorMsg]) identdefs :: Int -> Env -> [(Id, Type, Exp ())] -> ([(Id, Type, Exp Attr)], Env, [ErrorMsg]) LiU-FP2016: Lecture 7 p.10/52 Answer to Conundrum: Monads (1) Monads bridges the gap: allow effectful programming in a pure setting. Key idea: Computational types: an object of type MA denotes a computation of an object of type A. Thus we shall be both pure and impure, whatever takes our fancy! Monads originated in Category Theory. Adapted by - Moggi for structuring denotational semantics - Wadler for structuring functional programs LiU-FP2016: Lecture 7 p.13/52 Example 1: A Simple Evaluator data Exp Lit Integer Add Exp Exp Sub Exp Exp Mul Exp Exp Div Exp Exp eval :: Exp -> Integer eval (Lit n) n eval (Add e1 e2) eval e1 + eval e2 eval (Sub e1 e2) eval e1 - eval e2 eval (Mul e1 e2) eval e1 * eval e2 eval (Div e1 e2) eval e1 div eval e2 LiU-FP2016: Lecture 7 p.16/52 Example: A Compiler Fragment (8) identdefs l env [] ([], env, []) identdefs l env ((i,t,e) : ds) ((i,t,e ) : ds, env, ms1++ms2++ms3) (e, ms1) identaux l env e (env, ms2) case entervar i l t env of Left env -> (env, []) Right m -> (env, [m]) (ds, env, ms3) identdefs l env ds LiU-FP2016: Lecture 7 p.11/52 Answer to Conundrum: Monads (2) Monads promote disciplined use of effects since the type reflects which effects can occur; allow great flexibility in tailoring the effect structure to precise needs; support changes to the effect structure with minimal impact on the overall program structure; allow integration into a pure setting of real effects such as - I/O - mutable state. LiU-FP2016: Lecture 7 p.14/52 Making the Evaluator Safe (1) data Maybe a Nothing Just a safeeval (Lit n) Just n Just n2 -> Just (n1 + n2) LiU-FP2016: Lecture 7 p.17/52 Example: A Compiler Fragment (9) Error checking and collection of error messages arguably added a lot of clutter. The core of the algorithm is this: identdefs l env [] ([], env) identdefs l env ((i,t,e) : ds) ((i,t,e ) : ds, env ) e identaux l env e env entervar i l t env (ds, env ) identdefs l env ds Errors are just a side effect. This Lecture Pragmatic introduction to monads: Effectful computations Identifying a common pattern Monads as a design pattern Making the Evaluator Safe (2) safeeval (Sub e1 e2) Just n2 -> Just (n1 - n2) LiU-FP2016: Lecture 7 p.12/52 LiU-FP2016: Lecture 7 p.15/52 LiU-FP2016: Lecture 7 p.18/52

Making the Evaluator Safe (3) Sequencing Evaluations Aside: Scope Rules ofλ-abstractions safeeval (Mul e1 e2) Just n2 -> Just (n1 * n2) evalseq :: Maybe Integer -> (Integer -> Maybe Integer) -> Maybe Integer evalseq ma f case ma of Just a -> f a The scope rules of λ-abstractions are such that parentheses can be omitted:... Just (n1 + n2)... LiU-FP2016: Lecture 7 p.19/52 LiU-FP2016: Lecture 7 p.22/52 LiU-FP2016: Lecture 7 p.25/52 Making the Evaluator Safe (4) safeeval (Div e1 e2) Just n2 -> if n2 0 then Nothing else Just (n1 div n2) LiU-FP2016: Lecture 7 p.20/52 Exercise 1: RefactoringsafeEval RewritesafeEval, caseadd, usingevalseq: Just n2 -> Just (n1 + n2) evalseq ma f case ma of Just a -> f a LiU-FP2016: Lecture 7 p.23/52 Refactored Safe Evaluator (1) safeeval (Lit n) Just n Just (n1 + n2) safeeval (Sub e1 e2) Just (n1 - n2) LiU-FP2016: Lecture 7 p.26/52 Any Common Pattern? Exercise 1: Solution Refactored Safe Evaluator (2) Clearly a lot of code duplication! Can we factor out a common pattern? We note: Sequencing of evaluations (or computations). If one evaluation fails, fail overall. Otherwise, make result available to following evaluations. evalseq (safeeval e1) (\n1 -> evalseq (safeeval e2) (\n2 -> Just (n1+n2))) or safeeval e1 evalseq (\n1 -> safeeval e2 evalseq (\n2 -> Just (n1 + n2))) safeeval (Mul e1 e2) Just (n1 * n2) safeeval (Div e1 e2) if n2 0 then Nothing else Just (n1 div n2) LiU-FP2016: Lecture 7 p.21/52 LiU-FP2016: Lecture 7 p.24/52 LiU-FP2016: Lecture 7 p.27/52

InliningevalSeq (1) Just (n1 + n2) Just a -> (\n1 -> safeeval e2...) a Maybe Viewed as a Computation (1) Consider a value of typemaybe a as denoting a computation of a value of typea that may fail. When sequencing possibly failing computations, a natural choice is to fail overall once a subcomputation fails. I.e. failure is an effect, implicitly affecting subsequent computations. Let s generalize and adopt names reflecting our intentions. The Safe Evaluator Revisited safeeval (Lit n) mbreturn n safeeval e1 mbseq \n1 -> safeeval e2 mbseq \n2 -> mbreturn (n1 + n2)... safeeval (Div e1 e2) safeeval e1 mbseq \n1 -> safeeval e2 mbseq \n2 -> if n2 0 then mbfail else mbreturn (n1 div n2))) LiU-FP2016: Lecture 7 p.28/52 LiU-FP2016: Lecture 7 p.31/52 LiU-FP2016: Lecture 7 p.34/52 InliningevalSeq (2) safeeval e2 evalseq (\n2 ->...) Just a -> (\n2 ->...) a Maybe Viewed as a Computation (2) Successful computation of a value: mbreturn :: a -> Maybe a mbreturn Just Sequencing of possibly failing computations: mbseq :: Maybe a -> (a -> Maybe b) -> Maybe b mbseq ma f case ma of Just a -> f a Example 2: Numbering Trees data Tree a Leaf a Node (Tree a) (Tree a) numbertree :: Tree a -> Tree Int numbertree t fst (ntaux t 0) ntaux :: Tree a -> Int -> (Tree Int,Int) ntaux (Leaf _) n (Leaf n, n+1) ntaux (Node t1 t2) n let (t1, n ) ntaux t1 n in let (t2, n ) ntaux t2 n in (Node t1 t2, n ) LiU-FP2016: Lecture 7 p.29/52 LiU-FP2016: Lecture 7 p.32/52 LiU-FP2016: Lecture 7 p.35/52 InliningevalSeq (3) Just n2 -> (Just n1 + n2) Good excercise: verify the other cases. Maybe Viewed as a Computation (3) Failing computation: mbfail :: Maybe a mbfail Nothing Observations Repetitive pattern: threading a counter through a sequence of tree numbering computations. It is very easy to pass on the wrong version of the counter! Can we do better? LiU-FP2016: Lecture 7 p.30/52 LiU-FP2016: Lecture 7 p.33/52 LiU-FP2016: Lecture 7 p.36/52

Stateful Computations (1) A stateful computation consumes a state and returns a result along with a possibly updated state. The following type synonym captures this idea: type S a Int -> (a, Int) (OnlyInt state for the sake of simplicity.) A value (function) of types a can now be viewed as denoting a stateful computation computing a value of typea. Stateful Computations (4) Reading and incrementing the state (For ref.:s a Int -> (a, Int)): sinc :: S Int sinc \n -> (n, n + 1) Comparison of the examples Both examples characterized by sequencing of effectful computations. Both examples could be neatly structured by introducing: - A type denoting computations - A function constructing an effect-free computation of a value - A function constructing a computation by sequencing computations In fact, both examples are instances of the general notion of a MONAD. LiU-FP2016: Lecture 7 p.37/52 LiU-FP2016: Lecture 7 p.40/52 LiU-FP2016: Lecture 7 p.43/52 Stateful Computations (2) When sequencing stateful computations, the resulting state should be passed on to the next computation. I.e. state updating is an effect, implicitly affecting subsequent computations. (As we would expect.) LiU-FP2016: Lecture 7 p.38/52 Numbering trees revisited data Tree a Leaf a Node (Tree a) (Tree a) numbertree :: Tree a -> Tree Int numbertree t fst (ntaux t 0) ntaux :: Tree a -> S (Tree Int) ntaux (Leaf _) sinc sseq \n -> sreturn (Leaf n) ntaux (Node t1 t2) ntaux t1 sseq \t1 -> ntaux t2 sseq \t2 -> sreturn (Node t1 t2 ) LiU-FP2016: Lecture 7 p.41/52 Monads in Functional Programming A monad is represented by: A type constructor M :: * -> * M T represents computations of a value of typet. A polymorphic function return :: a -> M a for lifting a value to a computation. A polymorphic function (>>) :: M a -> (a -> M b) -> M b for sequencing computations. LiU-FP2016: Lecture 7 p.44/52 Stateful Computations (3) Computation of a value without changing the state (For ref.:s a Int -> (a, Int)): sreturn :: a -> S a sreturn a \n -> (a, n) Sequencing of stateful computations: sseq :: S a -> (a -> S b) -> S b sseq sa f \n -> let (a, n ) sa n in f a n Observations The plumbing has been captured by the abstractions. In particular: - counter no longer manipulated directly - no longer any risk of passing on the wrong version of the counter! Exercise 2:join andfmap Equivalently, the notion of a monad can be captured through the following functions: return :: a -> M a join :: (M (M a)) -> M a fmap :: (a -> b) -> (M a -> M b) join flattens a computation,fmap lifts a function to map computations to computations. Definejoin andfmap in terms of>> (and return), and>> in terms ofjoin andfmap. (>>) :: M a -> (a -> M b) -> M b LiU-FP2016: Lecture 7 p.39/52 LiU-FP2016: Lecture 7 p.42/52 LiU-FP2016: Lecture 7 p.45/52

Exercise 2: Solution join :: M (M a) -> M a join mm mm >> id fmap :: (a -> b) -> M a -> M b fmap f m m >> \a -> return (f a) or: fmap :: (a -> b) -> M a -> M b fmap f m m >> return. f (>>) :: M a -> (a -> M b) -> M b m >> f join (fmap f m) Exercise 3: Solution return :: a -> I a return id (>>) :: I a -> (a -> I b) -> I b m >> f f m -- or: (>>) flip ($) Simple calculations verify the laws, e.g.: return x>> f id x>> f x>> f f x Reading Philip Wadler. The Essence of Functional Programming. Proceedings of the 19th ACM Symposium on Principles of Programming Languages (POPL 92), 1992. Nick Benton, John Hughes, Eugenio Moggi. Monads and Effects. In International Summer School on Applied Semantics 2000, Caminha, Portugal, 2000. All About Monads. http://www.haskell.org/all_about_monads LiU-FP2016: Lecture 7 p.46/52 LiU-FP2016: Lecture 7 p.49/52 LiU-FP2016: Lecture 7 p.52/52 Monad laws Additionally, the following laws must be satisfied: return x>> f f x m>>return m (m>> f)>> g m>> (λx f x>> g) I.e.,return is the right and left identity for>>, and>> is associative. Monads in Category Theory (1) The notion of a monad originated in Category Theory. There are several equivalent definitions (Benton, Hughes, Moggi 2000): Kleisli triple/triple in extension form: Most closely related to the>> version: A Klesili triple over a category C is a triple (T,η, _ ), T : C C, η A : A TA for A C, f : TA TB for f : A TB. (Additionally, some laws must be satisfied.) LiU-FP2016: Lecture 7 p.47/52 LiU-FP2016: Lecture 7 p.50/52 Exercise 3: The Identity Monad The Identity Monad can be understood as representing effect-free computations: type I a a 1. Provide suitable definitions ofreturn and >>. 2. Verify that the monad laws hold for your definitions. Monads in Category Theory (2) Monad/triple in monoid form: More akin to thejoin/fmap version: A monad over a category C is a triple (T,η,µ), T : C C is a functor, η : id C T and µ : T 2 T are natural transformations. (Additionally, some commuting diagrams must be satisfied.) LiU-FP2016: Lecture 7 p.48/52 LiU-FP2016: Lecture 7 p.51/52