Presentation is loading. Please wait.

Presentation is loading. Please wait.

Advanced Functional Programming

Similar presentations


Presentation on theme: "Advanced Functional Programming"— 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”

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 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 Tvar(Just _ ) Tuple[ X, Y]

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 GUI a State t a Parser 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 is a type constructor which has an implied action.
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 Do { x <- Do { y <- b; c } ; d } =
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 Then we could model IO a as follows
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. Actions can be composed.
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.


Download ppt "Advanced Functional Programming"

Similar presentations


Ads by Google