Programovací jazyky F# a OCaml Chapter 6. Sequence expressions and computation expressions (aka monads)

Slides:



Advertisements
Similar presentations
Decision Structures - If / Else If / Else. Decisions Often we need to make decisions based on information that we receive. Often we need to make decisions.
Advertisements

Programovací jazyky F# a OCaml Chapter 4. Generic and recursive types.
Pemrograman VisualMinggu …2… Page 1 MINGGU Ke Dua Pemrograman Visual Pokok Bahasan: Console Application Tujuan Instruksional Khusus: Mahasiswa dapat menjelaskan.
1 Programming Languages (CS 550) Lecture Summary Functional Programming and Operational Semantics for Scheme Jeremy R. Johnson.
Getting started with ML ML is a functional programming language. ML is statically typed: The types of literals, values, expressions and functions in a.
Programovací jazyky F# a OCaml Chapter 3. Composing primitive types into data.
Programovací jazyky F# a OCaml Chapter 2. Refactoring code using functions.
Introduction to Computing Science and Programming I
Chapter 51 Scripting With JSP Elements JavaServer Pages By Xue Bai.
Computer Science 1620 Loops.
Loops – While Loop Repetition Statements While Reading for this Lecture, L&L, 5.5.
Iteration This week we will learn how to use iteration in C++ Iteration is the repetition of a statement or block of statements in a program. C++ has three.
Introduction to ML - Part 2 Kenny Zhu. What is next? ML has a rich set of structured values Tuples: (17, true, “stuff”) Records: {name = “george”, age.
Chapter 5: Loops and Files.
Loops – While, Do, For Repetition Statements Introduction to Arrays
Copyright ©2009 Opher Etzion Event Processing Course Filtering and transformation (Relates to Chapter 8)
Parallelism COS 597C David August David Walker. Goals To compare and contrast a variety of different programming languages and programming styles –imperative.
Lecture Review (If-else Statement) if-else statement has the following syntax: if ( condition ) { statement1; } else { statement2; } The condition.
CHAPTER 10 Recursion. 2 Recursive Thinking Recursion is a programming technique in which a method can call itself to solve a problem A recursive definition.
ECE122 L9: While loops March 1, 2007 ECE 122 Engineering Problem Solving with Java Lecture 9 While Loops.
Chapter 4: Looping CSCI-UA 0002 – Introduction to Computer Programming Mr. Joel Kemp.
Programovací jazyky F# a OCaml Chapter 5. Hiding recursion using function-as-values.
REPETITION STRUCTURES. Topics Introduction to Repetition Structures The while Loop: a Condition- Controlled Loop The for Loop: a Count-Controlled Loop.
Microsoft Visual Basic 2008 CHAPTER NINE Using Arrays and File Handling.
Chapter 5: Control Structures II (Repetition)
Using Arrays and File Handling
PROGRAMMING IN VISUAL BASIC.NET VISUAL BASIC BUILDING BLOCKS Bilal Munir Mughal 1 Chapter-5.
ASP.NET Programming with C# and SQL Server First Edition Chapter 3 Using Functions, Methods, and Control Structures.
Chapter 5 Control Structures: Loops 5.1 The while Loop The while loop is probably the most frequently used loop construct. The while loop is a conditional.
Java Threads. What is a Thread? A thread can be loosely defined as a separate stream of execution that takes place simultaneously with and independently.
Logic Our programs will have to make decisions on what to do next –we refer to the decision making aspect as logic Logic goes beyond simple if and if-else.
© 2006 Pearson Education 1 More Operators  To round out our knowledge of Java operators, let's examine a few more  In particular, we will examine the.
Chapter 5: Control Structures II (Repetition). Objectives In this chapter, you will: – Learn about repetition (looping) control structures – Learn how.
Saeed Ghanbartehrani Summer 2015 Lecture Notes #5: Programming Structures IE 212: Computational Methods for Industrial Engineering.
Logic Our programs will have to make decisions in terms of what to do next –we refer to the decision making aspect as logic Logic goes beyond simple if.
Java server pages. A JSP file basically contains HTML, but with embedded JSP tags with snippets of Java code inside them. A JSP file basically contains.
Reactive pattern matching for F# Part of “Variations in F#” research project Tomáš Petříček, Charles University in Prague
CIS 842: Specification and Verification of Reactive Systems Lecture INTRO-Examples: Simple BIR-Lite Examples Copyright 2004, Matt Dwyer, John Hatcliff,
Loops and Files. 5.1 The Increment and Decrement Operators.
1 Standard Version of Starting Out with C++, 4th Brief Edition Chapter 5 Looping.
C++ Programming: Program Design Including Data Structures, Fourth Edition Chapter 6: User-Defined Functions I.
Question of the Day  Move one matchstick to produce a square.
1 CSC 222: Computer Programming II Spring 2004 Stacks and recursion  stack ADT  push, pop, top, empty, size  vector-based implementation, library 
CMPSC 16 Problem Solving with Computers I Spring 2014 Instructor: Tevfik Bultan Lecture 4: Introduction to C: Control Flow.
Copyright 2006 Addison-Wesley Brief Version of Starting Out with C++ Chapter 5 Looping.
Lecture 7 – Repetition (Loop) FTMK, UTeM – Sem /2014.
Programming in Java (COP 2250) Lecture 12 & 13 Chengyong Yang Fall, 2005.
Evolution of C and C++ n C was developed by Dennis Ritchie at Bell Labs (early 1970s) as a systems programming language n C later evolved into a general-purpose.
CMSC 104, Section 301, Fall Lecture 18, 11/11/02 Functions, Part 1 of 3 Topics Using Predefined Functions Programmer-Defined Functions Using Input.
4 - Conditional Control Structures CHAPTER 4. Introduction A Program is usually not limited to a linear sequence of instructions. In real life, a programme.
1 Agenda  Unit 7: Introduction to Programming Using JavaScript T. Jumana Abu Shmais – AOU - Riyadh.
Functional Processing of Collections (Advanced) 6.0.
//liveVirtualacademy2011/ What’s New for ASP.NET 4.5 and Web Development in Visual Studio 11 Developer Preview Γιώργος Καπνιάς MVP, MCT, MCDP, MCDBA, MCTS,
1 COMS 261 Computer Science I Title: C++ Fundamentals Date: September 23, 2005 Lecture Number: 11.
Ms N Nashandi Dr SH Nggada Week 08 – Recursion. Outline We shall be covering the following What is a recursion? Iteration versus Recursion. Recursion.
REPETITION CONTROL STRUCTURE
Loop Structures.
Closures and Streams cs784(Prasad) L11Clos
Algorithm Analysis CSE 2011 Winter September 2018.
Functional Processing of Collections (Advanced)
CSE 341: Programming Langs
12 Asynchronous Programming
Alternate Version of STARTING OUT WITH C++ 4th Edition
FP Foundations, Scheme In Text: Chapter 14.
T. Jumana Abu Shmais – AOU - Riyadh
Algorithm Discovery and Design
CS 36 – Chapter 11 Functional programming Features Practice
Lesson #6 Modular Programming and Functions.
Flowcharts and Pseudo Code
Lecture 6 - Recursion.
Presentation transcript:

Programovací jazyky F# a OCaml Chapter 6. Sequence expressions and computation expressions (aka monads)

Sequence expressions 1. (generating sequences)

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Lazily generated sequences of values Sequence expressions > let nums = seq { let n = 10 yield n + 1 printfn "second.." yield n + 2 };; val nums : seq > nums |> List.ofSeq;; second.. val it : int list = [11; 12] > nums |> Seq.take 1 |> List.ofSeq;; val it : int list = [11] seq identifier specifies that we’re writing sequence expression We can use all standard F# Generates next element Nothing runs yet! Calculate all elements Move to first yield only

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Sequences can be composed using yield! Sequence expressions let capitals = [ "London"; "Prague" ] let withNew(x) = seq { yield x yield "New " + x } let allCities = seq { yield "Seattle" yield! capitals yield! withNew("York") } Standard list of values Function that generates sequence with two elements Yield all elements of the list Yield both generated names

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Thanks to yield! we can use recursion Recursive call in tail-cal position is optimized We can write infinite sequences too… Generating complex sequences let rec range(nfrom, nto) = seq { if (nfrom < nto) then yield nfrom yield! range(nfrom + 1, nto) } Recursive function Terminates sequence if false Tail-call like situation let rec numbers(nfrom) = seq { yield nfrom yield! numbers(nfrom + 1) }

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, Working with sequences using HOFs, working with infinite sequences DEMO

Sequence expressions 2. (processing sequences)

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Calculate squares of all numbers… »“Cross join” of two sequences let cities = [ ("New York", "USA"); ("London", "UK"); ("Cambridge", "UK"); ("Cambridge", "USA") ] let entered = [ "London"; "Cambridge" ] seq { for name in entered do for (n, c) in cities do if n = name then yield sprintf "%s from %s" n c } Processing sequences let squares = seq { for n in numbers(0) do yield n * n } Iterate over the source Generate 0 or more elements to output… Find 0 or more matching cities

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Each for translated to a call to collect First step, replace the outer for: Second step, replace the inner for: entered |> Seq.collect (fun name -> cities |> Seq.collect (fun (n, c) -> if n = name then [ sprintf "%s from %s" n c ] else [])) How does it work? entered |> Seq.collect (fun name -> seq { for (n, c) in cities do if n = name then yield sprintf "%s from %s" n c })

Computation expressions

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »A type M with two operations: Bind operation: Return operation: Algebraically : some axioms should be true… Seq.singleton : 'a -> seq Option.Some : 'a -> option Introducing monads… Option.bind : ('a -> option ) -> option -> option Seq.collect : ('a -> seq ) -> seq -> seq

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Multiplying elements in sequences »Writing similar computation for options… Syntax with for and yield is used with sequences… Introducing monads… seq { for n in numbers1 do for m in numbers2 do yield n * m } option { for n in tryReadInt() do for m in tryReadInt() do yield n * m } option { let! n = tryReadInt() let! m = tryReadInt() return n * m }

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, ValuesInput #1Input #2Output Lists[2; 3][10; 100][20; 200; 30; 300] OptionsSome(2)Some(10)Some(20) OptionsSome(2)None OptionsNone(not required)None Behavior for sample inputs

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »The code is translated to member calls… let! – translated to “Bind” operation return – translated to “Return” operation How does it work? option { let! n = tryReadInt() let! m = tryReadInt() return n * m } option.Bind(tryReadInt(), fun n -> option.Bind(tryReadInt(), fun m -> let add = n + m let sub = n - m value.Return(n * m) ))

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Simple object type with two members: More about objects in the next lecture :-) »Members should have the usual types: Implementing builder type OptionBuilder() = member x.Bind(v, f) = v |> Option.bind f member x.Return(v) = Some(v) let option = new OptionBuilder() Bind : ('a -> M ) -> M -> M Return : 'a -> M

Computation expression for “resumptions”

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »We want to run a computation step-by-step E.g. someone calls our “tick” operation It should run only for a reasonably long time »How to write calculations that take longer? We can run one step during each “tick” How to turn usual program into stepwise code? »Example: Visual Studio IDE and IntelliSense Motivation

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »First step: We need to define a type representing the computation or the result Computation that may fail: option Computation returning multiple values: seq »The Resumption type: Either finished or a function that runs next step Designing computation expression type Resumption = | NotYet of (unit -> Resumption ) | Result of 'a

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Second step: Defining ‘bind’ and ‘return’: Return should have a type 'a -> Resumption Bind is more complicated. The type should be: Implementing computation expression let returnR v = Result(v) Resump -> ('a -> Resump ) -> Resump let rec bindR v f = NotYet(fun () -> match v with | NotYet calcV -> bindR (calcV()) f | Result value -> f value) ‘v’ already took some time to run We return result as the next step Return the rest of the computation Run the next step and then bind again…

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Third step: Computation builder »Writing code using resumptions: Designing computation expression type ResumptionBuilder() = member x.Bind(v, f) = bindR v f member x.Return(v) = returnR v let resumable = new ResumptionBuilder() Builder instance let foo(arg) = expensiceCalc(arg) let bar() = let a = foo(1) let b = foo(2) a + b Returns ‘int’ let foo(arg) = resumable { return expensiceCalc(arg) } let bar() = resumable { let! a = foo(1) let! b = foo(2) return a + b } Single-step resumption Compose steps Returns Resumption

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, Programming with resumptions DEMO

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Writing code using resumptions Simple transformation of source code Add “resumable { }” and let! with return »Using resumptions Step-by-step evaluation of computations Micro-threading – nonpreemtive parallelism (interleaving execution of multiple resumables) Resumptions summary

Asynchronous workflows

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Downloading web pages from the internet: Motivation open System open System.Net open System.IO let syncDownload(url:string) = let req = WebRequest.Create(url) let rsp = req.GetResponse() use stream = rsp.GetResponseStream() use reader = new StreamReader(stream) let html = reader.ReadToEnd() printfn "%s" html let urls = [ " ] for url in urls do syncDownload(url) Initialize request Send request (can take long time!) Download page (can take long time!)

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Performing slow or unreliable I/O Can take a long time and may fail We don’t want to block the current thread! »Run operation on a background thread? Threads are expensive (on Windows) We’re just waiting! Not doing anything useful »The right approach: Asynchronous calls Motivation

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, ».NET provides BeginXyz methods… Asynchronous calls in.NET let uglyAsyncDownload(url:string) = let req = WebRequest.Create(url) req.BeginGetResponse((fun ar1 -> let rsp = req.EndGetResponse(ar1) use stream = rsp.GetResponseStream() use reader = new StreamReader(stream) let html = reader.ReadToEnd() printfn "%s" html ), null) |> ignore for url in urls do uglyAsyncDownload(url) Runs the function when response is received Oops! There is no BeginReadToEnd Starts all computations

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Asynchronous workflows Computation that eventually calculates some result and then calls the provided function »The Async type (simplified): The F# solution… type Async = | Async of (('a -> unit) -> unit) Takes a continuation ('a -> unit) Returns nothing now. When the operation completes (later), invokes the continuation

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »Downloading web pages using workflows Asynchronous workflows #r "FSharp.PowerPack.dll" open Microsoft.FSharp.Control.WebExtensions let asyncDownload(url:string) = async { let req = WebRequest.Create(url) let! rsp = req.AsyncGetResponse() use stream = rsp.GetResponseStream() use reader = new StreamReader(stream) let! html = reader.AsyncReadToEnd() printfn "%s" html } [ for url in urls do yield asyncDownload(url) ] |> Async.Parallel |> Async.RunSynchronously Reference necessary libraries & namespaces asynchronous operation List of computations to run Compose & run them

NPRG049— Programovací jazyky OCaml a F#Tomáš Petříček, »We can use standard control structures Recursion or even imperative F# features Asynchronous workflows let asyncReadToEnd(stream:Stream) = async { let ms = new MemoryStream() let read = ref -1 while !read <> 0 do let buffer = Array.zeroCreate 1024 let! count = stream.AsyncRead(buffer, 0, 1024) ms.Write(buffer, 0, count) read := count ms.Seek(0L, SeekOrigin.Begin) |> ignore return (new StreamReader(ms)).ReadToEnd() }