Curry A Tasty dish? Haskell Curry!. Curried Functions Currying is a functional programming technique that takes a function of N arguments and produces.

Slides:



Advertisements
Similar presentations
1 Programming Languages (CS 550) Mini Language Interpreter Jeremy R. Johnson.
Advertisements

1 Scheme and Functional Programming Aaron Bloomfield CS 415 Fall 2005.
Intermediate Code Generation
Scheme in Scheme. Why implement Scheme in Scheme  Implementing a language is a good way to learn more about programming languages  Interpreters are.
Logic Programming (cont’d): Lists Lists in Prolog are represented by a functor (similar to cons in Scheme): 1.The empty list is represented by the constant.
CSE 3341/655; Part 4 55 A functional program: Collection of functions A function just computes and returns a value No side-effects In fact: No program.
Functional Programming. Pure Functional Programming Computation is largely performed by applying functions to values. The value of an expression depends.
CS 355 – PROGRAMMING LANGUAGES Dr. X. Apply-to-all A functional form that takes a single function as a parameter and yields a list of values obtained.
331 Final Fall Details 3:30-5:30 Monday, December 16 ITE 229 (this room!) Comprehensive with more emphasis on material since the midterm Look at.
Fall 2008Programming Development Techniques 1 Topic 9 Symbol Manipulation Generating English Sentences Section This is an additional example to symbolic.
Fall 2008Programming Development Techniques 1 Topic 2 Scheme and Procedures and Processes September 2008.
C. Varela; Adapted w/permission from S. Haridi and P. Van Roy1 Declarative Computation Model Defining practical programming languages Carlos Varela RPI.
Mark Hennessy Dept. Computer Science NUI Maynooth 1 CaML continued CS 351 Programming Paradigms Dept. Computer Science NUI Maynooth.
ML: a quasi-functional language with strong typing Conventional syntax: - val x = 5; (*user input *) val x = 5: int (*system response*) - fun len lis =
Copyright © 2006 The McGraw-Hill Companies, Inc. Programming Languages 2nd edition Tucker and Noonan Chapter 14 Functional Programming It is better to.
CS 330 Programming Languages 11 / 18 / 2008 Instructor: Michael Eckmann.
Functional programming: LISP Originally developed for symbolic computing First interactive, interpreted language Dynamic typing: values have types, variables.
Chapter 3: Formal Translation Models
Type Inference: CIS Seminar, 11/3/2009 Type inference: Inside the Type Checker. A presentation by: Daniel Tuck.
PPL Syntax & Formal Semantics Lecture Notes: Chapter 2.
PPL Syntax & Formal Semantics Lecture Notes: Chapter 2.
F UNCTIONAL P ROGRAMMING 05 Functions. F UNCTIONS - G LOBAL F UNCTIONS fboundp Tells whether there is a function with a given symbol as its name > (fboundp.
Functional Programming Element of Functional Programming.
ITEC 380 Organization of programming languages Lecture 2 – Grammar / Language capabilities.
ISBN Chapter 15 Functional Programming Languages.
331 Final Spring Details 6-8 pm next Monday Comprehensive with more emphasis on material since the midterm Study example finals and midterm exams.
Functional Programming in Scheme and Lisp. Overview In a functional programming language, functions are first class objects. You can create them, put.
Functional Programming and Lisp. Overview In a functional programming language, functions are first class objects. In a functional programming language,
Artificial Intelligence IES 503 Asst. Prof. Dr. Senem Kumova Metin.
CSC 580 – Theory of Programming Languages, Spring, 2009 Week 9: Functional Languages ML and Haskell, Dr. Dale E. Parson.
Copyright © Curt Hill Languages and Grammars This is not English Class. But there is a resemblance.
Functional Programming in Scheme and Lisp.
COP4020 Programming Languages Functional Programming Prof. Xin Yuan.
Chapter Fifteen: Functional Programming Languages Lesson 12.
A Third Look At ML Chapter NineModern Programming Languages, 2nd ed.1.
331 Final Fall Details 3:30-5:30 Friday December 17 th LH4 Comprehensive with more emphasis on material since the midterm Study example finals and.
CSE 230 The -Calculus. Background Developed in 1930’s by Alonzo Church Studied in logic and computer science Test bed for procedural and functional PLs.
Variables, Environments and Closures. Overview Touch on the notions of variable extent and scope Introduce the notions of lexical scope and dynamic.
CMSC 330: Organization of Programming Languages Functional Programming with OCaml.
Milos Hauskrecht (PDF) Hieu D. Vu (PPT) LISP PROGARMMING LANGUAGE.
1/33 Basic Scheme February 8, 2007 Compound expressions Rules of evaluation Creating procedures by capturing common patterns.
Fall 2008Programming Development Techniques 1 Topic 17 Assignment, Local State, and the Environment Model of Evaluation Section 3.1 & 3.2.
CS 330 Programming Languages 11 / 28 / 2006 Instructor: Michael Eckmann.
1 FP Foundations, Scheme In Text: Chapter Chapter 14: FP Foundations, Scheme Mathematical Functions Def: A mathematical function is a mapping of.
Forms Writing your own procedures CS 480/680 – Comparative Languages.
PPL Syntax & Formal Semantics Lecture Notes: Chapter 2.
1 Simple Lisp Programs References:
1 PROGRAMMING IN HASKELL An Introduction Based on lecture notes by Graham Hutton The book “Learn You a Haskell for Great Good” (and a few other sources)
Functional Programming
Functional Programming Languages
Functional Programming
Introduction to Higher Order (Functional Programming) (Python) part 2
LISP – (LISt Processing)
System Software Unit-1 (Language Processors) A TOY Compiler
Higher-Order Procedures
PROGRAMMING IN HASKELL
FP Foundations, Scheme In Text: Chapter 14.
Type & Typeclass Syntax in function
6.001 SICP Further Variations on a Scheme
CSCE 314: Programming Languages Dr. Dylan Shell
Lisp and Scheme I.
Streams and Lazy Evaluation in Lisp and Scheme
6.001 SICP Variations on a Scheme
Announcements Quiz 5 HW6 due October 23
LISP LISt Processing.
Curry A Tasty dish? Haskell Curry!.
CSE S. Tanimoto Lambda Calculus
topics interpreters meta-linguistic abstraction eval and apply
Common Lisp II.
Lambda Expressions Cases
Presentation transcript:

Curry A Tasty dish? Haskell Curry!

Curried Functions Currying is a functional programming technique that takes a function of N arguments and produces a related one where some of the args are fixed > (define add10 (curry + 10)) > (add10 3) 13 > (define triple (curry * 3)) > (triple 5) 15

A tasty dish? Currying was named after the Mathematical logician Haskell Curry ( )Haskell Curry Curry worked on combinatory logic …combinatory logic A technique that eliminates the need for variables in mathematical logic …mathematical logic and hence computer programming! – at least in theory The functional programming language Haskell is also named in honor of Haskell CurryHaskell

Functions in Haskell In Haskell we can define g as a function that takes two arguments of types a and b and returns a value of type c like this: – g :: (a, b) -> c We can let f be the curried form of g by – f = curry gcurry The function f now has the signature – f :: a -> b -> c f takes an arg of type a & returns a function that takes an arg of type b & returns a value of type c

Functions in Haskell All functions in Haskell are curried, i.e., all Haskell functions take just single arguments. This is mostly hidden in notation, and is not apparent to a new Haskeller Let's take the function div :: Int -> Int -> Int which performs integer divisiondivInt The expression div 10 2 evaluates to 5div But it's a two-part process – div 10 is evaled & returns a function of type Int -> Int divInt – That function is applied to the value 2, yielding 5

Currying in Scheme Scheme has an explicit built in function, curry, that takes a function and some of its arguments and returns a curried function For example: – (define add10 (curry + 10)) – (define triple (curry * 3)) We could define this easily as: (define (curry fun. args) (lambda x (apply fun (append args x))))

Note on lambda syntax (lambda X (foo X)) is a way to define a lambda expression that takes any number of arguments In this case X is bound to the list of the argument values, e.g.: > (define f (lambda x (print x))) > f # > (f ) ( ) >

Simple example (a) Compare two lists of numbers pair wise: (apply and (map < ‘( ) '( ))) Note that (map < ‘( ) '( )) evaluates to the list (#t #t #t #t) Applying and to this produces the answer, #t

Simple example (b) Is every number in a list positive? (apply and (map < 0 ' ( ))) This is a nice idea, but will not work map: expects type as 2nd argument, given: 0; other arguments were: # ( ) === context === /Applications/PLT/collects/scheme/private/misc.ss:74:7 Map takes a function and lists for each of its arguments

Simple example (c) Is every number in a list positive? Use (lambda (x) (< 0 x)) as the function (apply and (map (lambda (x) (< 0 x)) '( ))) This works nicely and gives the right answer What we did was to use a general purpose, two-argument comparison function (?<?) to make a narrower one-argument one (0<?)

Simple example (d) Here’s where curry helps (curry < 0) ≈ (lambda (x) (< 0 x)) So this does what we want (apply and (map (curry < 0) '( ))) – Currying < with 0 actually produces (lambda x (apply < 0 x)) – So (curry < 0) takes one or more args, e.g. ((curry #t ((curry #f

A real world example I wanted to adapt a Lisp example by Google’s Peter Norvig of a simple program that generates random sentences from a context free grammar Peter Norvig It was written to take the grammar and start symbol as global variables  I wanted to make this a parameter, but it made the code more complex   Scheme’s curry helped solve this!

cfg1.ss #lang scheme ;;; This is a simple … (define grammar '((S -> (NP VP) (NP VP) (NP VP) (NP VP) (S CONJ S)) (NP -> (ARTICLE ADJS? NOUN PP?)) (VP -> (VERB NP) (VERB NP) (VERB NP) VERB) (ARTICLE -> the the the a a a one every) (NOUN -> man ball woman table penguin student book dog worm computer robot ) … (PP -> (PREP NP)) (PP? -> () () () () PP) ))

scheme> scheme Welcome to MzScheme v4.2.4 … > (require "cfg1.ss") > (generate 'S) (a woman took every mysterious ball) > (generate 'S) (a blue man liked the worm over a mysterious woman) > (generate 'S) (the large computer liked the dog in every mysterious student in the mysterious dog) > (generate ‘NP) (a worm under every mysterious blue penguin) > (generate ‘NP) (the book with a large large dog) cfg1.ss cfg1.ss session

cfg1.ss #lang scheme ;;; This is a simple … (define grammar '((S -> (NP VP) (NP VP) (NP VP) (NP VP) (S CONJ S)) (NP -> (ARTICLE ADJS? NOUN PP?)) (VP -> (VERB NP) (VERB NP) (VERB NP) VERB) (ARTICLE -> the the the a a a one every) (NOUN -> man ball woman table penguin student book dog worm computer robot ) … (PP -> (PREP NP)) (PP? -> () () () () PP) )) Five possible rewrites for a S: 80% of the time it => NP VP and 20% of the time it is a conjoined sentence, S CONJ S Terminal symbols (e.g, the, a) are recognized by virtue of not heading a grammar rule. () is like ε in a rule, so 80% of the time a PP? produces nothing and 20% a PP.

(define (generate phrase) ;; generate a random sentence or phrase from grammar (cond ((list? phrase) (apply append (map generate phrase))) ((non-terminal? phrase) (generate (random-element (rewrites phrase)))) (else (list phrase)))) (define (non-terminal? x) ;; True iff x is a on-terminal in grammar (assoc x grammar))assoc (define (rewrites non-terminal) ;; Return a list of the possible rewrites for non-terminal in grammar (rest (rest (assoc non-terminal grammar)))) (define (random-element list) ;; returns a random top-level element from list (list-ref list (random (length list))))list-ref random cfg1.ss If phrase is a list, like (NP VP), then map generate over it and append the results If a non-terminal, select a random rewrite and apply generate to it. It’s a terminal, so just return a list with it as the only element.

Parameterizing generate Let’s change the package to not use global variables for grammar The generate function will take another parameter for the grammar and also pass it to non-terminal? and rewrites While we are at it, we’ll make both param- eters to generate optional with appropriate defaults

> (load "cfg2.ss") > (generate) (a table liked the blue robot) > (generate grammar 'NP) (the blue dog with a robot) > (define g2 '((S -> (a S b) (a S b) (a S b) ()))) > (generate g2) (a a a a a a b b b b b b) > (generate g2) (a a a a a a a a a a a b b b b b b b b b b b) > (generate g2) () > (generate g2) (a a b b) cfg2.ss cfg2.ss session

cfg2.ss (define default-grammar '((S -> (NP VP) (NP VP) (NP VP) (NP VP))...)) (define default-start 'S) (define (generate (grammar default-grammar) (phrase default-start)) ;; generate a random sentence or phrase from grammar (cond ((list? phrase) (apply append (map generate phrase))) ((non-terminal? phrase grammar) (generate grammar (random-element (rewrites phrase grammar)))) (else (list phrase))))) (define (non-terminal? x grammar) ;; True iff x is a on-terminal in grammar (assoc x grammar)) (define (rewrites non-terminal grammar) ;; Return a list of the possible rewrites for non-terminal in grammar (rest (rest (assoc non-terminal grammar)))) Global variables define defaults optional parameters Pass value of grammar to subroutines Subroutines take new parameter

cfg2.ss (define default-grammar '((S -> (NP VP) (NP VP) (NP VP) (NP VP))...)) (define default-start 'S) (define (generate (grammar default-grammar) (phrase default-start)) ;; generate a random sentence or phrase from grammar (cond ((list? phrase) generate (apply append (map generate phrase))) ((non-terminal? phrase grammar) (generate grammar (random-element (rewrites phrase grammar)))) (else (list phrase))))) (define (non-terminal? x grammar) ;; True iff x is a on-terminal in grammar (assoc x grammar)) (define (rewrites non-terminal grammar) ;; Return a list of the possible rewrites for non-terminal in grammar (rest (rest (assoc non-terminal grammar)))) generate takes 2 args – we want the 1 st to be grammar’s current value and the 2 nd to come from the list

cfg2.ss (define default-grammar '((S -> (NP VP) (NP VP) (NP VP) (NP VP))...)) (define default-start 'S) (define (generate (grammar default-grammar) (phrase default-start)) ;; generate a random sentence or phrase from grammar (cond ((list? phrase) (curry generate grammar) (apply append (map (curry generate grammar) phrase))) ((non-terminal? phrase grammar) (generate grammar (random-element (rewrites phrase grammar)))) (else (list phrase))))) (define (non-terminal? x grammar) ;; True iff x is a on-terminal in grammar (assoc x grammar)) (define (rewrites non-terminal grammar) ;; Return a list of the possible rewrites for non-terminal in grammar (rest (rest (assoc non-terminal grammar))))

Partial evaluation in Python Python has partial evaluation, which is like currying >>> from functools import partial >>> def add(x,y): return x + y >>> add10 = partial(add, 10) >>> add10(5) 15 With partial you can easily create a function that fixes the first N args or any keyword args

Curried functions Curried functions have lots of applications in programming language theory The curry operator is also a neat trick in our functional programming toolbox I’ve used it in both scheme and python to produce a customized version of a complex function with one or more arguments fixed You can add them to Python and other languages, if the underlying language has the right support