1 / 30

Advanced Functional Programming

Advanced Functional Programming. Tim Sheard Oregon Graduate Institute of Science & Technology. Lecture 5: Monads Generic Unification Monads. Reading Assignment. Read the paper “Generic Unification via Two-Level Types and Parameterized Modules”

sandeew
Download Presentation

Advanced Functional Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Advanced Functional Programming • Tim Sheard • Oregon Graduate Institute of Science & Technology • Lecture 5: Monads • Generic Unification • Monads

  2. Reading Assignment • Read the paper • “Generic Unification via Two-Level Types and Parameterized Modules” • http://www.cse.ogi.edu/~sheard/courses/cse583W03/papers/index.html

  3. An Example Use • Unification of types is used for type inference. • data (Mutable ref m ) => • Type ref m = • Tvar (ref (Maybe (Type ref m))) • | Tgen Int • | Tarrow (Type ref m) (Type ref m) • | Ttuple [Type ref m] • | Tcon String [Type ref m]

  4. Unify • unify :: Mutable ref m => • (Type ref m -> Type ref m -> m [String]) -> • Type ref m -> Type ref m -> m [String] • unify occursAction x y = • do { t1 <- prune x • ; t2 <- prune y • ; case (t1,t2) of • (Tvar r1,Tvar r2) -> • if same r1 r2 • then return [] • else do { put r1 (Just t2); return []} • (Tvar r1,_) -> • do { b <- occursIn r1 t2 • ; if b then occursAction t1 t2 • else do { put r1 (Just t2) • ; return [] } • }

  5. Unify continued • unify occursAction x y = • do { t1 <- prune x • ; t2 <- prune y • ; case (t1,t2) of • . . . • (_,Tvar r2) -> unify occursAction t2 t1 • (Tgen n,Tgen m) -> • if n==m then return [] • else return ["generic error"] • (Tarrow a b,Tarrow x y) -> • do { e1 <- unify occursAction a x • ; e2 <- unify occursAction b y • ; return (e1 ++ e2) • } • (_,_) -> return ["shape match error"] • }

  6. Generic Unify • How can we generalize unify to work on any type? • What properties must that type have? • a variable constructor like Tvar with a reference • What functions best capture these properties? • Capture these functions in a class. • class Mutable ref m => Unify t ref m where • isVar:: t ref m -> Maybe (ref (Maybe (t ref m))) • occursCheck :: ref(Maybe (t ref m)) -> t ref m -> m Bool • occursAction :: t ref m -> t ref m -> m [String] • match :: t ref m -> t ref m -> Maybe [(t ref m, t ref m)]

  7. Tvar(Just _ ) Tvar(Just _ ) Tvar(Just _ ) Tvar(Just _ ) Tvar(Just _ ) Tvar(Just _ ) Tuple[ X, Y] Tuple[ X, Y] Generic Prune • prunefun :: Unify t ref m => t ref m -> m(t ref m) • prunefun typ = • case isVar typ of • Just r -> do { m <- get r • ; case m of • Just t -> do { newt <- prunefun t • ; put r (Just newt) • ; return newt • } • Nothing -> return typ} • Nothing -> return typ

  8. Generic Unify • uni :: Unify t ref m => t ref m -> t ref m -> m[String] • uni x y = • do { t1 <- prunefun x • ; t2 <- prunefun y • ; case (isVar t1,isVar t2) of • (Just r1,Just r2) -> • if same r1 r2 • then return [] • else do { put r1 (Just t2); return []} • (Just r1,_) -> • do { b <- occursCheck r1 t2 • ; if b then occursAction t1 t2 • else do { put r1 (Just t2); return [] }} • (_,Just r2) -> uni t2 t1 • (Nothing,Nothing) -> case match t1 t2 of • Just pairs -> • do { errs <- sequence (map (uncurry uni) pairs) • ; return (concat errs) } • Nothing -> return["Match error"] • }

  9. An instance • instance Unify Type IORef IO where • isVar (Tvar r) = Just r • isVar _ = Nothing • occursCheck = occursIn • occursAction x y = return ["Occurs Check error"] • match x y = • let mlist xs ys = if length xs == length ys • then Just(zip xs ys) • else Nothing • in case (x,y) of • (Tgen x,Tgen y) -> • if x==y then Just [] else Nothing • (Tarrow x y,Tarrow a b) -> Just[(x,a),(y,b)] • (Ttuple xs,Ttuple ys) -> mlist xs ys • (Tcon c xs,Tcon d ys) -> • if c==d then mlist xs ys else Nothing

  10. Monads • Monads & Actions • A Monad is an Abstract Data Type (ADT) • A Monad encapsulates effects • i.e. hides their implementation • A Monad uses types to separates Actions from pure computations • A Monad controls the order of effects

  11. Actions • It is sometimes useful to use actions or side effects in a functional program . • Update a piece of state (assignment) • do some IO • draw graphics on a display • return an exception rather than an answer • How do we do this? • We use a Monad • A Monad is a type constructor which has an implied action. • For example: IO Int is an action which performs some IO and then returns an Int

  12. Example Monads • IO a • Perform an IO action (like read or write to a file or stdin or stdout) and then return an item of type: a • GUI a • Perform a GUI action (like draw a pull-down menu) and then return an item of type: a • State t a • Perform an action which could change the value of a mutable variable (like an assignment) in a state thread t, and then return an item of type: a • Parser a • Read some input to build an item of type: a, then chop the items used to build it off the input device. Also a parse may fail so must handle failure as well.

  13. A monad is an ADT • A monad is an abstract datatype • It abstracts computations with effects. • It hides the details of its implementation. • It exports an abstract interface. • It specifies the order in which effects occur. • It separates pure computations from effectfull ones using the type system. • It can have multiple implementations.

  14. Monads Encapsulate Effects • A monad captures the meaning and use of computations which have effects on the real world. • A monad describes or specifies the effects in a “purely functional” way. • A monad allows one to reason about effects, using the simple rule of substitution of equals for equals. • A monad needn’t be implemented this way

  15. Sample Effects or Actions • State • Update a piece of the store (assignment) as well as return a final value. • Exceptional cases • There may be an error instead of a final value • Non-determinism • There may be multiple possible final values • Partial Computation • There may be nothing: no final value, or anything else • Communication • There may be external influence on the computation • Perform some Input or Output, as well as a final value. • Draw graphics on a display

  16. A Monad uses types to separate Actions (with effects) from pure computations • A Monad is a type constructor which has an implied action. • For example: • a computation with type (IO Int ) • an action which might perform some IO and which then returns an Int • Computations with non-monadic types cannot have any effects. They are pure computations. The user (and the compiler) can rely on this.

  17. A monad orders effects • A Monad specifies which effects come before others. • The Do operator provides this control over the order in which computations occur • do { var <- location x -- the first action • ; write var (b+1) -- the next action • }

  18. A monad’s interface hides details • A monad has an interface that hides the details of its implementation • Every monad has at least the two operations • Do Lets users control the order of actions • Return : a -> Action a makes an empty action • Each monad has its own additional operations.

  19. Monads have Axioms • Order matters (and is maintained by Do) • Do { x <- Do { y <- b; c } • ; d } = • Do { y <- b; x <- c; d } • Return introduces no effects • Do { x <- Return a; e } = e[a/x] • Do { x <- e; Return x } = e

  20. An Example: IO actions • Each function performs an action of doing some IO • ? :t getChar -- get 1 char from stdin • getChar :: IO Char • ? :t putChar -- put Char to stdout • putChar :: Char -> IO() • ? :t getLine -- get a whole line from stdin • getLine :: IO String • ? :t readFile -- read a file into a String • readFile :: FilePath -> IO String • ? :t writeFile -- write a String to a file • writeFile :: FilePath -> String -> IO ()

  21. Modelling IO • Suppose all that IO captured was the reading and writing to standard input and output. • Then we could model IO a as follows • data Io a = • Io ( String -> (a,String,String)) • instance Monad Io where • return x = Io(\ s -> (x,s,"")) • (>>=) (Io f) g = • Io(\ s -> let (x,in1,out1) = f s • (Io h) = g x • (y,in2,out2) = h in1 • in (y,in2,out1 ++ out2))

  22. Io operations • getCharX :: Io Char -- get 1 char from stdin • getCharX = Io(\ (c:cs) -> (c,cs,"")) • putCharX :: Char -> Io() -- put Char to stdout • putCharX c = Io(\ s -> ((),s,[c])) • getLineX :: Io String -- get a whole line from stdin • getLineX = do { c <- getCharX • ; if c == '\n' • then return "" • else do { cs <- getLineX • ; return (c:cs) • } }

  23. How to perform an IO action • Some thing of type: IO Int is a potential action which will return an Int, if it is ever performed. • In order for the action to occur, it must be performed. • Any thing with type : IO a typed at top level will be performed. • This is the only way that an action can be performed. • Stated another way • An actionful program builds up a potential action, which is finally performed when typed at top-level. • laziness is crucial in the implementation here • Big actionful programs can be built by combining smaller actionful programs using do. • No action is ever performed until typed at top level.

  24. Example: Combining IO actions • getLineX :: Io [Char] • getLineX = • do { c <- getCharX -- get a char • ; if c == '\n' -- if its newline • then return "" -- no-op action which • -- returns empty string • -- recursively • else do { l <- getLine' -- get a line • ; return (c:l) -- no-op action • } -- to cons c to l • } • Potentially reads a string from stdin, if it is ever performed

  25. Observations • Actions are first class. • They can be abstracted (param’s of functions) • Stored in data structures. -- It is possible to have a list of actions, etc. • Actions can be composed. • They can be built out of smaller actions by glueing them together with do and return • They are sequenced with do much like one uses semi-colon in languages like Pascal and C. • Actions can be performed (run). • separation of construction from performance is key to their versatility. • Actions of type: Action () are like statements in imperative languages. • They are used only for their side effects.

  26. Performing an action • How do we perform an action? • We need a function with type: • Io a -> a • If we have such a function then we break the abstraction which hides how Io is implemented. • In Haskell, the real IO can only be preformed at top level, when because the main function must have type IO()

  27. Modelling Io • Some Monads have models. • A model is a pure function that simulates the actions of the monad in a pure way. • Our Io monad is a model of a subset of the IO monad. • If a Monad has a model, we can often produce a run function with type: • m a -> model_of_m a • The run function uses the actual effects, but hides them in the model.

  28. The Model of Io • run (IO f) = f • Suppose the only thing IO did was getchar and putchar, then then run might be implemented as: • run g s = • { stdout := "" • ; x= perform g using s as input • ; return (x,stdin,stdout) • }

  29. Sample Monads • data Id x = Id x • data Exception x = Ok x | Fail • data Env e x = Env (e -> x) • data Store s x = Store (s -> (x,s)) • data Mult x = Mult [x] • data Output x = Output (x,String)

  30. Homework • Make Haskell Class definitions for each of the monad types on the previous page. • Think about what other operations are usefull for each monad and define those. • Recast the monad laws from the lecture interms of return and (>>=) instead of return and do. • Choose 2 of the monads. • The first should be either Exception or Output • The second should be one of Env, Store, Mult • prove the order or bind law for the two monads you choose.

More Related