Fusion-powered EDSLs

Similar documents
Parsing. Zhenjiang Hu. May 31, June 7, June 14, All Right Reserved. National Institute of Informatics

EECS 700 Functional Programming

Structurally Recursive Descent Parsing. Nils Anders Danielsson (Nottingham) Joint work with Ulf Norell (Chalmers)

Introduction to Haskell

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

CSCE 314 Programming Languages. Monadic Parsing

CSCE 314 Programming Languages. Functional Parsers

Monad Overview (3B) Young Won Lim 1/16/18

CIS552: Advanced Programming

Lecture C-10: Parser Combinators - Introduction

Parsing CSP-CASL with Parsec

Programming in Haskell Aug Nov 2015

Monads. Functional Programming (CS4011) Monads

CSE 413 Languages & Implementation. Hal Perkins Winter 2019 Structs, Implementing Languages (credits: Dan Grossman, CSE 341)

Haskell for (E)DSLs. Andres Löh. Functional Programming exchange, 16 March Well-Typed LLP

CSCE 314 TAMU Fall CSCE 314: Programming Languages Dr. Flemming Andersen. Functional Parsers

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

CS 11 Haskell track: lecture 1

Skeletons and the Anatomy of Monads

Monads. Bonus lecture 2017 David Sands

Compilers and computer architecture From strings to ASTs (2): context free grammars

Haskell Monads CSC 131. Kim Bruce

University of Utrecht. 1992; Fokker, 1995), the use of monads to structure functional programs (Wadler,

CSCE 314 Programming Languages. Monadic Parsing

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

CS 209 Functional Programming

Monads seen so far: IO vs Gen

Functional Programming. Pure Functional Languages

6. Pointers, Structs, and Arrays. March 14 & 15, 2011

Improving Query Plans. CS157B Chris Pollett Mar. 21, 2005.

CS 415 Midterm Exam Spring 2002

CS 360: Programming Languages Lecture 10: Introduction to Haskell

7. Introduction to Denotational Semantics. Oscar Nierstrasz

Racket. CSE341: Programming Languages Lecture 14 Introduction to Racket. Getting started. Racket vs. Scheme. Example.

CIS 194: Homework 3. Due Wednesday, February 11, Interpreters. Meet SImPL

Concepts of programming languages

College Functors, Applicatives

6. Pointers, Structs, and Arrays. 1. Juli 2011

Principles of Compiler Construction ( )

Introducing Wybe a language for everyone

Talen en Compilers. Jurriaan Hage , period 2. November 13, Department of Information and Computing Sciences Utrecht University

Monadic Parsing. 1 Chapter 13 in the book Programming in Haskell (2nd ed.) by. 2 Chapters 10 and 16 in the book Real World Haskell by Bryan

Principles of Programming Languages [PLP-2015] Detailed Syllabus

Introduction to Scheme

To figure this out we need a more precise understanding of how ML works

CS 370 The Pseudocode Programming Process D R. M I C H A E L J. R E A L E F A L L

Expressions. Parsing Expressions. Showing and Reading. Parsing. Parsing Numbers. Expressions. Such as. Can be modelled as a datatype

CS 275 Name Final Exam Solutions December 16, 2016

Parsing Expressions. Slides by Koen Lindström Claessen & David Sands

UNIVERSITY OF CALIFORNIA

Applicative, traversable, foldable

INFOB3TC Solutions for the Exam

Refactoring to Functional. Hadi Hariri

Lecture 09: Data Abstraction ++ Parsing is the process of translating a sequence of characters (a string) into an abstract syntax tree.

Applicative, traversable, foldable

Introduction to Parsing

Introduction to Prolog Paper Refs. Prolog tutor. Julian Verdurmen. Seminar Softw. tech. for teaching and learning. September 30, 2009

Data Abstraction. An Abstraction for Inductive Data Types. Philip W. L. Fong.

The name of our class will be Yo. Type that in where it says Class Name. Don t hit the OK button yet.

CSCI-GA Scripting Languages

Template Haskell based implementation of printf

Once VS2015 is configured to build C# projects, create a new Visual C#, ASP.NET Web application. Select Web Forms

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

CSCC24 Functional Programming Scheme Part 2

EECS 700 Functional Programming

CS1 Recitation. Week 1

Homework & Announcements

Principles of Programming Languages COMP251: Syntax and Grammars

Thoughts on Assignment 4 Haskell: Flow of Control

UNIT I Programming Language Syntax and semantics. Kainjan Sanghavi

Structural polymorphism in Generic Haskell

Representing Cyclic Structures as Nested Datatypes. Makoto Hamana

CS 360: Programming Languages Lecture 12: More Haskell

CS 415 Midterm Exam Spring SOLUTION

Principles of Compiler Construction ( )

CS Exam #1-100 points Spring 2011

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

Tracing Ambiguity in GADT Type Inference

Introduction to Functional Programming in Haskell 1 / 56

6.001 Notes: Section 6.1

CS32 - Week 1. Umut Oztok. June 24, Umut Oztok CS32 - Week 1

Haskell Syntax in Functions

CSE 505: Concepts of Programming Languages

Don t write anything in the field marked Eventuell ekstra ID. For each subtask, choose the answer you think is the most correct one.

Haskell Introduction Lists Other Structures Data Structures. Haskell Introduction. Mark Snyder

CS131 Compilers: Programming Assignment 2 Due Tuesday, April 4, 2017 at 11:59pm

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

CSE 12 Abstract Syntax Trees

Standard ML. Data types. ML Datatypes.1

Stop coding Pascal. Saturday, April 6, 13

The Worker/Wrapper Transformation

Lazy Functional Programming in Haskell

Lecture 5: Declarative Programming. The Declarative Kernel Language Machine. September 12th, 2011

Types, Expressions, and States

Note that in this definition, n + m denotes the syntactic expression with three symbols n, +, and m, not to the number that is the sum of n and m.

CSE413: Programming Languages and Implementation Racket structs Implementing languages with interpreters Implementing closures

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

Syntax/semantics. Program <> program execution Compiler/interpreter Syntax Grammars Syntax diagrams Automata/State Machines Scanning/Parsing

CS152: Programming Languages. Lecture 11 STLC Extensions and Related Topics. Dan Grossman Spring 2011

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

Transcription:

Fusion-powered EDSLs Philippa Cowderoy flippa@flippac.org Fusion-powered EDSLs p.

Outline What is fusion? Anatomy of an EDSL Shallow vs deep embedding Examples: Identity & State monads Self-analysing EDSL implementations Summary, Wishlist, Questions Fusion-powered EDSLs p.

What is Fusion? Given: A "producer" A "consumer" We can often rewrite the expression consumer producer so that there is no intermediate value. e.g. map f (map g xs) map (f.g) xs Result of producer must only used by consumer: Otherwise we still need the intermediate! Fusion-powered EDSLs p.

Anatomy of an EDSL Language primitives: char, >>=, catch, atomic Non-primitive combinators and helpers: many, mapm, chainl1 Execution functions: runp arser, runerror, runt ot heshops Analyses: Error-checking, grammar analyses, possible optimisations... Fusion-powered EDSLs p.

Anatomy of an EDSL Syntax Constructors: producers, form an algebra >>=, catch, mapm, chainl1 Internal Representation Deconstructors: consumers, form a coalgebra runp arser, runerror Semantics Fusion-powered EDSLs p.

Shallow Embedding type Parser a = String -> [(a,string)] char :: Char -> Parser Char char c (c :s) c == c = [(c,s)] char = []... runparser :: Parser a -> String -> runparser = ($) [(a,string)] Fusion-powered EDSLs p.

Deep Embedding data Parser a where... Char :: Char -> Parser Char runparser :: Parser a -> String -> [(a,string)]... runparser (Char c) (c :s) c == c = [(c,s)] runparser (Char c) _ = [] Fusion-powered EDSLs p.

Shallow vs Deep Embedding Deep Shallow Structure Intermediate No intermediate Primitive Denote syntax Denote semantics Constructors Hard to add? Easily added? Primitive syntax semantics Trivial Deconstructors easily added hard to add Fusion-powered EDSLs p.

A Trivial Fusion Example data Id a where Return :: a -> Id a Bind :: Id a -> (a -> Id b) -> Id b runidentity :: Id a -> a runidentity (Return v) = v runidentity (Bind l fr) = let l = runidentity l r = fr l in runidentity r Fusion-powered EDSLs p.

A Trivially Transformed Example Change types: newtype Id a = {runidentity::a} Rewrite the implementation according to: (return, bind) = runidentity(return, Bind) Result: return v = Id v bind l fr = Id f where f = let l = runidentity l r = fr l in runidentity r

State Monad data State s a where... Bind :: State s r -> (r -> State s a) -> State s a Get :: State s s runstate :: State s a -> s -> (s,a) runstate (Bind c1 f) s0 = let (s1,r1) = runstate c1 s0 c2 = f r1 in runstate c2 s1 runstate Get s = (s,s)

Stating the Obvious? data State s a = State {runstate :: s -> (s,a)} bind c1 f = State c where c s0 = let (s1,r1) = runstate c1 s0 c2 = f r1 in runstate c2 s1 get = State c where c s = (s,s) Note: runstate :: State s a -> s -> (s,a) => State s a = State {runstate :: s -> (s,a)}

DSLs that Think Too Much What if we want to do self-analysis like those shiny parsing combinators? Isn t that hard? Not really!

Parsing data Parser r where Char :: Char -> Parser Char Ap :: Parser a -> Parser (a -> r) -> Parser r Pure :: r -> Parser r Choice :: Parser r -> Parser r -> Parser r Empty :: Parser r Many :: Parser r -> Parser [r] A simple Applicative parser. Grammar is context-free - never determined by intermediate results - so we can analyse it.

Mere semantics? Here are the semantic functions: runparser :: Parser a -> String -> Maybe (a, String) firsts :: Parser a -> Map Char (Parser a) runparser calls firsts, using a first set analysis to speed itself up. Moving to a shallow embedding, we need to carry two values in the record: newtype Parser a = Parser {runparser :: String -> Maybe a, firsts :: Map Char (Parser a)

Results Memoisation of static results for free! Still room for further efficiency gains - e.g. swapping Maybe for a more efficient error monad, attacking the usual memory leak problem There s plenty of room for small optimisations, but many of them can be made to the original version of the code too or left to well-known GHC optimisations. Control.Applicative.many (like many other functions that use general recursion) messes up the static analysis whether in deep or shallow form :-(

Summary To translate from deep to shallow: Replace the term datatype with a record type - a field for each semantic function Replace the term constructors with records - the fields containing the constructor s case from each semantic function Don t worry about sharing/exploiting laziness in the deep version, the shallow one will do it automatically!

Wishlist Better support for object-level recursion - this probably means sugar Why am I fusing all this stuff by hand anyway? I know all the conditions required to make it work! Pointed syntactic sugar for Applicatives would be nice Something for my parser s toothache?

Finish Both the slides from this talk and a lengthier parsing example will be available on the web from http://flippac.org/talks/ and linked to from the AngloHaskell 2008 page. Any questions?