Monads. foo1 Method to print a string, then return its length: scala> def foo1(bar: String) = { | println(bar) | bar.size | } foo1: (bar: String)Int scala>

Slides:



Advertisements
Similar presentations
Intro to Scala Lists. Scala Lists are always immutable. This means that a list in Scala, once created, will remain the same.
Advertisements

A Third Look At ML 1. Outline More pattern matching Function values and anonymous functions Higher-order functions and currying Predefined higher-order.
Some non-recursive tricks. The Lambda expression. More on Let, Let*, apply and funcall.
More about functions Plus a few random things. 2 Tail recursion A function is said to be tail recursive if the recursive call is the very last thing it.
CS162 Week 2 Kyle Dewey. Overview Continuation of Scala Assignment 1 wrap-up Assignment 2a.
Recap 1.Programmer enters expression 2.ML checks if expression is “well-typed” Using a precise set of rules, ML tries to find a unique type for the expression.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
Patterns in ML functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are the.
Python November 18, Unit 7. So Far We can get user input We can create variables We can convert values from one type to another using functions We can.
28-Jun-15 Using Objects. 2 Overview In this presentation we will discuss: Classes and objects Methods for objects Printing results.
29-Jun-15 Using Objects. 2 Classes and objects The type of an object is the class that describes that object If we say int count, the type of count is.
Characters and Strings. Characters In Java, a char is a primitive type that can hold one single character A character can be: –A letter or digit –A punctuation.
Methods. Why methods? A method gives a name to something that you want to do, so you don’t have to think about how to do it, you just do it The name should.
Chapter TwelveModern Programming Languages1 Memory Locations For Variables.
Functional Programing Referencing material from Programming Language Pragmatics – Third Edition – by Michael L. Scott Andy Balaam (Youtube.com/user/ajbalaam)
FUNCTIONS. Function call: >>> type(32) The name of the function is type. The expression in parentheses is called the argument of the function. Built-in.
Pattern matching. The if expression The else part of an if expression is optional if ( condition ) expression1 else expression2 If the condition evaluates.
Haskell Chapter 8. Input and Output  What are I/O actions?  How do I/O actions enable us to do I/O?  When are I/O actions actually performed?
CST8177 bash Scripting Chapters 13 and 14 in Quigley's "UNIX Shells by Example"
Scala Overview Brandon Clopton CSCI 431. Scala fuses object-oriented and functional programming in a statically typed programming language. It is aimed.
Patterns in OCaml functions. Formal vs. actual parameters Here's a function definition (in C): –int add (int x, int y) { return x + y; } –x and y are.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
Templates An introduction. Simple Template Functions template T max(T x, T y) { if (x > y) { return x; } else { return y; } } int main(void) { int x =
Chapter 9: Functional Programming in a Typed Language.
Built-in Data Structures in Python An Introduction.
Functional Programming With examples in F#. Pure Functional Programming Functional programming involves evaluating expressions rather than executing commands.
1 Functional Programming Lecture 6 - Algebraic Data Types.
Functions and Methods. Definitions and types A function is a piece of code that takes arguments and returns a result A pure function is a function whose.
© M. Winter COSC 4P41 – Functional Programming Programming with actions Why is I/O an issue? I/O is a kind of side-effect. Example: Suppose there.
Python Functions.
A Third Look At ML Chapter NineModern Programming Languages, 2nd ed.1.
0 Odds and Ends in Haskell: Folding, I/O, and Functors Adapted from material by Miran Lipovaca.
CMSC 330: Organization of Programming Languages Functional Programming with OCaml.
Cases and Classes and Case Classes And Other Miscellany 16-Dec-15.
Lee CSCE 314 TAMU 1 CSCE 314 Programming Languages Interactive Programs: I/O and Monads Dr. Hyunyoung Lee.
Classes and Objects and Traits And Other Miscellany 25-Jan-16.
CSE 130 : Spring 2011 Programming Languages Ranjit Jhala UC San Diego Lecture 5: Functions and Closures.
Functional Programming IN NON-FUNCTIONAL LANGUAGES.
FUNCTIONAL PROGRAMING AT WORK - HASKELL AND DOMAIN SPECIFIC LANGUAGES Dr. John Peterson Western State Colorado University.
OOP Basics Classes & Methods (c) IDMS/SQL News
Haskell Chapter 5, Part II. Topics  Review/More Higher Order Functions  Lambda functions  Folds.
Quiz 3 Topics Functions – using and writing. Lists: –operators used with lists. –keywords used with lists. –BIF’s used with lists. –list methods. Loops.
CSE-321 Programming Languages Introduction to Functional Programming POSTECH March 8, 2006 박성우.
24-Jun-16 Haskell Dealing with impurity. Purity Haskell is a “pure” functional programming language Functions have no side effects Input/output is a side.
Haskell Chapter 8.
CS-104 Final Exam Review Victor Norman.
Organization of Programming Languages
PROGRAMMING IN HASKELL
Functions Inputs Output
Haskell Dealing with impurity 30-Nov-18.
CISC101 Reminders Assn 3 due tomorrow, 7pm.
Plus a few random things
And why they are so useful
PROGRAMMING IN HASKELL
Type & Typeclass Syntax in function
Python Tutorial for C Programmer Boontee Kruatrachue Kritawan Siriboon
Fundamentals of Functional Programming
Plus a few random things
6.001 SICP Variations on a Scheme
Clojure Macros.
Haskell Dealing with impurity 8-Apr-19.
Programming Languages
Plus a few random things
Haskell Dealing with impurity 29-May-19.
CISC101 Reminders Assignment 3 due today.
Plus a few random things
Haskell Dealing with impurity 28-Jun-19.
Monads.
Plus a few random things
Plus a few random things
Presentation transcript:

Monads

foo1 Method to print a string, then return its length: scala> def foo1(bar: String) = { | println(bar) | bar.size | } foo1: (bar: String)Int scala> foo1("Hello") Hello res0: Int = 5 2

foo2 Here’s the same method, but replacing each expression with an anonymous function: scala> def foo1(bar: String) = { | (() => println(bar))() | (() => bar.length)() | } foo1: (bar: String)Int scala> foo2("Hello") Hello res1: Int = 5 3

andThen does sequencing scala> def double(x: Int) = 2 * x double: (x: Int)Int scala> def triple(x: Int) = 3 * x triple: (x: Int)Int scala> ((double _) andThen (triple _))(5) res4: Int = 30 scala> def upper(s: String) = s.toUpperCase upper: (s: String)String scala> def addXs(s: String) = "x" + s + "x" addXs: (s: String)String scala> ((upper _) andThen (addXs _))("Hello") res10: String = xHELLOx 4

andThen applied to foo Consider this form: def foo(bar: String) = { ({ () => println(bar) } andThen { () => bar.length })() } The above almost works… andThen is not defined for 0-argument functions Basically, what this achieves is sequencing in a purely functional manner In pure functions, there is no concept of sequencing 5

Thing Compare: def foo(i: Int) = i + 1 val a = 1 val b = foo(a) With: case class Thing[+A](value: A) val a = Thing(1) val b = Thing(2) def foo(i: Int) = Thing(i + 1) val a = Thing(1) val b = foo(a.value) The difference is that in the second, the value is “wrapped” in a Thing container 6

Monads as wrappers A monad consists of three things: A type constructor M A bind operation, (>>=) :: (Monad m) => m a -> (a -> m b) -> m b A return operation, return :: (Monad m) => a -> m a Is Thing a monad? It has a type constructor, Thing It has a return operation, Thing( i ) Let’s give it a bind operation: case class Thing[+A](value: A) { def bind[B](f: A => Thing[B]) = f(value) } 7

The Thing monad Here’s what we had before: scala> val a = Thing(1) a: Thing[Int] = Thing(1) scala> val b = foo(a.value) b: Thing[Int] = Thing(2) Here’s what we have now: scala> val a = Thing(1) a: Thing[Int] = Thing(1) scala> val b = a bind foo b: Thing[Int] = Thing(2) We have additional syntax, but really, nothing’s changed 8

The monad pattern Any time you start with something which you pull apart and use to compute a new something of that same type, you have a monad. val a = Thing(1) The first thing is that I can wrap up a value inside of a new Thing. Object- oriented developers might call this a “constructor”. Monads call it “the unit function”. Haskell calls it “return” (maybe we shouldn’t try to figure out that one just yet). a bind { i => Thing(i + 1) } We also have this fancy bind function, which digs inside our Thing and allows a function which we supply to use that value to create a new Thing. Scala calls this function “flatMap”. Haskell calls it “>>=”. …What’s interesting here is the fact that bind is how you combine two things together in sequence. 9 Directly quoted from

bind == flatMap Scala’s for expression is translated into map, flatMap, and withFilter operations Multiple generators lead to a flatMap for (x for (y <- expr 2 ; seq ) yield expr 3 ) Repeated use of flatMap will change List[List[List[ items ]]] into just List[ items ] 10

flatMap The flatMap method is like Map, but removes one level of nesting from a sequence scala> List(2, 3, 4, 5) map (x => List(x, x * x, x * x * x)) res21: List[List[Int]] = List(List(2, 4, 8), List(3, 9, 27), List(4, 16, 64), List(5, 25, 125)) scala> List(2, 3, 4, 5) flatMap (x => List(x, x * x, x * x * x)) res22: List[Int] = List(2, 4, 8, 3, 9, 27, 4, 16, 64, 5, 25, 125) Used with a sequence of Option, flatMap effectively reduces Some( x ) to x, and entirely deletes None scala> List(1, -1, 2, 4, -5, 9) flatMap (root(_)) res17: List[Double] = List(1.0, , 2.0, 3.0) 11

Using flatMap scala> for (v <- List(1, 2, 3, -1, 4)) { | val Some(rootOfV) = root(v) | println(rootOfV) | } scala.MatchError: None (of class scala.None$) scala> for (v <- List(1, 2, 3, -1, 4) flatMap (root(_))) println(v)

Option A value of type Option[T] can be either Some[ value ] or None, where value is of type T scala> def root(x: Double): Option[Double] = | if (x >= 0) Some(math.sqrt(x)) else None root: (x: Double)Option[Double] scala> root(10.0) res14: Option[Double] = Some( ) scala> root(-5.0) res15: Option[Double] = None 13

bind for Option sealed trait Option[+A] { def bind[B](f: A => Option[B]): Option[B] } case class Some[+A](value: A) extends Option[A] { def bind[B](f: A => Option[B]) = f(value) } case object None extends Option[Nothing] { def bind[B](f: Nothing => Option[B]) = None } 14

A “functional” println def foo(bar: String, stdout: Vector[String]) = { val stdout2 = println(bar, stdout) (bar.length, stdout2) } def println(str: String, stdout: Vector[String]) = stdout + str Functional input is trickier—we won’t go there Now let’s do this for everything! 15

Maintaining state A purely functional language has no notion of “state” (or time, or change…) Everything relevant to a function is in its parameters Therefore, a function that “changes state” must be called recursively with different parameters Consider an adventure game State includes the location of each object and the location of the player—this is easily done with a Map The state usually includes other information (is the dragon alive?)—we can put this in a tuple along with the Map Player’s actions can be implemented with a function that takes a State and computes a new State—that is, a monad 16

Life, the Universe, and Everything Passing around the entire “state of the universe” in parameters seems excessive, but… Typically a very large proportion of the information is immutable, and need not be part of the state You have to depend on the quality of the implementation of persistent data structures Scala has a specific State monad I haven’t explored this, but I’ve read that it’s complicated 17

And then there’s the IO monad… Haskell’s IO monad is like our earlier “functional” println, only richer and with a better syntax Like all monads, it pulls apart some kind of a thing, and creates a new thing from it The weird part is, I/O happens along the way Output doesn’t affect the result Input does affect the result The IO monad (1) achieves sequencing, and (2) isolates the I/O side effects from the rest of the program 18

Formal definition of a monad A monad consists of three things: A type constructor M A bind operation, (>>=) :: (Monad m) => m a -> (a -> m b) -> m b A return operation, return :: (Monad m) => a -> m a And the operations must obey some simple rules: return x >>= f = f x return just sends its result to the next function m >>= return = m Returning the result of an action is equivalent to just doing the action do {x <- m1; y <- m2; m3} = do {y <- do {x <- m1; m2} m3} >>= is associative

The End Substantial portions of this talk taken from: 20

Try scala> import scala.util.{Try, Success, Failure} import scala.util.{Try, Success, Failure} scala> def root2(x: Double): Try[Double] = | if (x >= 0) Success(math.sqrt(x)) else | Failure(new Exception("Imaginary root")) root2: (x: Double)scala.util.Try[Double] scala> root2(10) res28: scala.util.Try[Double] = Success( ) scala> root2(-10) res29: scala.util.Try[Double] = Failure(java.lang.Exception: Imaginary root) 21