├── SiML ├── LICENSE ├── Main.hs ├── Makefile ├── Setup.hs └── SiML.cabal ├── conduits.odp ├── dllist.odp ├── hsgems.odp ├── lambda.odp ├── monads.html ├── monads.odp ├── notawat.pdf ├── notawat.tex ├── numhaskell.odp ├── pdre-code ├── clojure-1.6.0.jar ├── jline-0.9.94.jar ├── pdre.clj └── repl ├── pdre.odp ├── pdrehs.odp ├── statictyping.odp ├── types.odp ├── types.pdf ├── types.tex ├── ultimateoo.odp └── webserve.odp /SiML/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, by Brian Hurt 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 11 | -------------------------------------------------------------------------------- /SiML/Main.hs: -------------------------------------------------------------------------------- 1 | 2 | import Text.ParserCombinators.Parsec 3 | 4 | main :: IO () 5 | main = putStrLn "Hello, world!" 6 | -------------------------------------------------------------------------------- /SiML/Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: .cabal-sandbox dist 3 | cabal build -j 4 | 5 | dist: 6 | cabal configure 7 | 8 | .cabal-sandbox: 9 | cabal sandbox init 10 | cabal install -j --enable-documentation --haddock-html --haddock-hoogle --only-dependencies 11 | 12 | .PHONY: clean 13 | clean: 14 | rm -rf dist 15 | 16 | .PHONY: clean 17 | cabal-clean: clean 18 | rm -rf cabal.sandbox.config .cabal-sandbox 19 | -------------------------------------------------------------------------------- /SiML/Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /SiML/SiML.cabal: -------------------------------------------------------------------------------- 1 | -- Initial SiML.cabal generated by cabal init. For further documentation, 2 | -- see http://haskell.org/cabal/users-guide/ 3 | 4 | name: SiML 5 | version: 0.1.0.0 6 | synopsis: A simple ML-like language to demonstrate Type Inference 7 | -- description: 8 | license: PublicDomain 9 | license-file: LICENSE 10 | author: Brian Hurt 11 | maintainer: bhurt42@gmail.com 12 | -- copyright: 13 | -- category: 14 | build-type: Simple 15 | -- extra-source-files: 16 | cabal-version: >=1.10 17 | 18 | executable SiML 19 | main-is: Main.hs 20 | -- other-modules: 21 | -- other-extensions: 22 | build-depends: base >=4.7, 23 | parsec >= 3.0 24 | -- hs-source-dirs: 25 | default-language: Haskell2010 26 | -------------------------------------------------------------------------------- /conduits.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/conduits.odp -------------------------------------------------------------------------------- /dllist.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/dllist.odp -------------------------------------------------------------------------------- /hsgems.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/hsgems.odp -------------------------------------------------------------------------------- /lambda.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/lambda.odp -------------------------------------------------------------------------------- /monads.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | A Monad Tutorial 4 | 5 | 6 |

Brian's Monad Tutorial

7 | 8 |

The Problems With Monad Tutorials

9 | 10 |

  1. Bad metaphors- "A monad is like a burrito wrapped in a space 11 | suit- it protects you from the toxic waste, and you can just reach in 12 | and grab all the apples you want." Solution: no metaphors, just 13 | code.
  2. 14 | 15 |
  3. Excess of category theory- "A monad is just a monoid in the category 16 | of endofunctors, what's the problem?" Solution: NO CATEGORY 17 | THEORY!
  4. 18 | 19 |
  5. A need for "hands on" experience- see Abstract Intuition and the Monad Tutoral Fallacy. 20 | Solution: stay concrete, lots of code, homework exercises. For our 21 | concrete examples, I borrow from the blog post 22 | You Could Have Invented Monads! (And Maybe You Already Have.). 23 |
  6. 24 | 25 |
  7. The "four faces" of monads:
    1. Where they come from (category 26 | theory)
    2. How they are implemented
    3. How they are 27 | used
    4. How they are thought about or designed with.
    28 | Solution: address each face separately, except the category theory which 29 | we don't need to address.
  8. 30 | 31 |
  9. Unfamiliarity with the concept of functions as data- many Monads are 32 | based around treating functions as data, and this is rare in other 33 | languages, and thus unfamiliar to most programmers. 34 | 35 |

36 | 37 |

Motivating Example #1

38 | 39 |

We have three functions, f, g, and h, so f calls g, and g calls h:

40 |

 41 |     f :: ... -> something
 42 |     f ... =
 43 |         ...
 44 |         let r = g ... in
 45 |         ...
 46 |         something
 47 | 
 48 |     g :: ... -> somethingElse
 49 |     g ... =
 50 |         ...
 51 |         let r = h ... in
 52 |         ...
 53 |         somethingElse
 54 | 
 55 |     h :: ... -> whatever
 56 |     h ... =
 57 |         ...
 58 | 

59 | 60 |

Now h needs some information (of type blah) from where f is called. So 61 | now we need to thread that information through the whole calling stack:

62 | 63 |

 64 |     f :: ... -> blah -> something
 65 |     f ... blah =
 66 |         ...
 67 |         let r = g ... blah in
 68 |         ...
 69 |         something
 70 | 
 71 |     g :: ... -> blah -> somethingElse
 72 |     g ... blah =
 73 |         ...
 74 |         let r = h ... blah in
 75 |         ...
 76 |         somethingElse
 77 | 
 78 |     h :: ... -> blah -> whatever
 79 |     h ... blah =
 80 |         ...
 81 | 

82 | 83 |

The Reader Type

84 | 85 |

I start by introducing a type:

86 | 87 |

 88 |     type Reader s a = s -> a
 89 | 

90 | 91 |

Note that the type declaration is Haskell is just like 92 | the typedef declaration in C/C++. All it does is introduce 93 | a type macro- I can always replace the type on the left with the type on 94 | the right. Indeed, I often will, to show what's going on under the hood 95 | (so to speak). So now we can clean up our types a little:

96 | 97 |

 98 |     f :: ... -> Reader blah something
 99 |     ...
100 | 
101 |     g :: ... -> Reader blah somethingElse
102 |     ...
103 | 
104 |     h :: ... -> Reader blah whatever
105 |     ...
106 | 

107 | 108 |

Note: in Haskell, functions are first class, which means it makes 109 | perfect sense to return a function as a value. Also, Haskell has 110 | partial function application- which means there is no difference between 111 | a function returning a function, and having the function just take that 112 | many more arguments. In other words:

113 | 114 |

115 |     -- A function that takes two arguments and returns some value
116 |     f foo bar = ...
117 | 

118 | 119 |

and:

120 | 121 |

122 |     -- A function that takes one argument and returns a function
123 |     -- that takes one argument and returns some value
124 |     f foo = (\bar ->  ...)
125 | 

126 | 127 |

are treate the same. It's even OK to do:

128 | 129 |

130 |     -- A function that takes one argument, does some stuff, and then
131 |     -- returns a function that takes one argument and returns some value
132 |     f foo = 
133 |         ...
134 |         (\bar ->  ...)
135 | 

136 | 137 |

These three different bits of code are all effectively 138 | equivalent.

139 | 140 |

We've improved the situation, but not much. What we need is a 141 | special "reader let", which automatically appends the blah value. This 142 | is hard, as it requires help from the compiler. We'll get back to that. 143 | However, there is something we can do now. A little know stunt in 144 | functional programming is that if we have:

145 | 146 |

147 |     -- A let expression.
148 |     let x = foo in bar
149 | 

150 | 151 |

we can replace it with:

152 | 153 |

154 |     -- a function expression applied to an argument.
155 |     (\x -> bar) foo
156 | 

157 | 158 |

And the code behaves the same. In fact, this is how let is defined 159 | in theory. Apply is much easier than let to replace in code. So, 160 | instead of a special let, let's do a special apply. Flip the order of 161 | the args, so we can do:

162 | 163 |

164 |     apply foo (\x -> bar)
165 | 

166 | 167 |

We want foo to have the type Reader s a, and we want the 168 | whole thing to have a return type of Reader s b, so we can 169 | go:

170 | 171 |

172 |     f :: ... -> Reader blah something
173 |     f ... =
174 |         ...
175 |         apply (g ...)
176 |             (\r ->
177 |                 ...
178 |                 something)
179 | 

180 | 181 |

and have apply do the right thing. And we can make an initial 182 | cut at the code:

183 | 184 |

185 | apply :: (Reader r a) -> (a -> b) -> Reader r b
186 | -- apply :: (r -> a) -> (a -> b) -> r -> b
187 | apply f g s = g (f s)
188 | 

189 | 190 |

This type signature looks familiar. Where have I seen it before?

191 | 192 |

193 |     fmap :: Functor f => (a -> b) -> f a -> f b
194 | 

195 | 196 |

But there is a problem: what happens if we want to call two functions 197 | and thread the variable into both?

198 | 199 |

200 |     f :: ... -> Reader blah something
201 |     f ... =
202 |         ...
203 |         apply (g ...)
204 |             (\r ->
205 |                 ...
206 |                 apply (g2 ...)
207 |                     (\r2 ->
208 |                         ...
209 |                         something))
210 | 

211 | 212 |

I can use fmap for the original apply, I want 213 | apply to have the type: (Reader r a) -> (a -> 214 | Reader r b) -> Reader r b. The apply function 215 | then becomes:

216 | 217 |

218 |     apply :: Reader r a -> (a -> Reader r b) -> Reader r b
219 |     -- apply :: (r -> a) -> (a -> r > b) -> r -> b
220 |     apply f g s = g (f s) s
221 | 

222 | 223 |

But this causes another problem:

224 | 225 |

226 |     f :: ... -> Reader blah something
227 |     f ... =
228 |         ...
229 |         apply (g ...)
230 |             (\r ->
231 |                 ...
232 |                 apply (g2 ...)
233 |                     (\r2 ->
234 |                         ...
235 |                         something)) -- Type error right here!
236 | 

237 | 238 |

The something expression has type 239 | something, but we want it to have type Reader blah 240 | something. We could user fmap, or we could just 241 | provide a fixup function:

242 | 243 |

244 |     fixup :: a -> Reader r a
245 |     -- fixup :: a -> r -> a
246 |     fixup x _ = x
247 | 

248 | 249 |

Now we can go:

250 | 251 |

252 |     f :: ... -> Reader blah something
253 |     f ... =
254 |         ...
255 |         apply (g ...)
256 |             (\r ->
257 |                 ...
258 |                 apply (g2 ...)
259 |                     (\r2 ->
260 |                         ...
261 |                         fixup something))
262 | 

263 | 264 |

I will, at this point, just rename apply to be the operator 265 | >>=, and the fixup function to 266 | return. This should start looking familiar:

267 | 268 |

269 |     f :: ... -> Reader blah something
270 |     f ... =
271 |         ...
272 |         (g ...) >>=
273 |             (\r ->
274 |                 ...
275 |                 (g2 ...) >>=
276 |                     (\r2 ->
277 |                         ...
278 |                         return something))
279 | 

280 | 281 |

Two last things we need, if we want to have Reader be an abstract 282 | data type (i.e., we don't let people see it's just a function under the 283 | hood). We need some way to call f with our initial blah. We need some 284 | function of type:

285 | 286 |

287 |     runReader :: Reader r a -> r -> a
288 | 

289 | 290 |

And, we need some way to access the read variable down where we need 291 | it (down in h). If we had a function:

292 | 293 |

294 |     ask :: Reader r r
295 | 

296 | 297 |

We could write h like:

298 | 299 |

300 |     h :: ... -> Reader blah whatever
301 |     h ... = ask (\blah -> ...)
302 | 

303 | 304 |

HOMEWORK: Implement the runReader and 305 | ask functions.

306 | 307 |

Performance

308 | 309 |

One of the concerns people have with writing this abstract code is 310 | the loss of performance- we're introducing a lot of unnecessary closures 311 | and lambda expressions. Rest assured, the ghc compiler optimizes all of 312 | this, and recovers code equalivalent to our original hand-threaded 313 | code. The ghc compiler knows about the let/apply equivalence (so it's 314 | not so unknown as I lead you to believe), and will happily convert back 315 | from our apply the (more efficient) let representation. Also, it knows 316 | about returning functions vr.s just taking more arguments, and will 317 | happily swap that back. We can write our nice, generic code, and 318 | Haskell will apply the obvious transformations to turn it into efficient 319 | code.

320 | 321 |

Motivating Example #2

322 | 323 |

Same as above, except now h doesn't just take a blah, it returns an 324 | updated blah (common with immutable data): 325 | 326 |

327 |     f :: ... -> blah -> (something, blah)
328 |     f ... blah =
329 |         ...
330 |         let (r, blah') = g ... blah in
331 |         ...
332 |         (something, blah')
333 | 
334 |     g :: ... -> blah -> (somethingElse, blah)
335 |     g ... blah =
336 |         ...
337 |         let (r, blah') = h ... blah in
338 |         ...
339 |         (somethingElse, blah')
340 | 
341 |     h :: ... -> blah -> (whatever, blah)
342 |     h ... blah =
343 |         ...
344 | 

345 | 346 |

The State Type

347 | 348 |

We pull the same trick, just a little more complicated. We 349 | define (spelling out the types):

350 | 351 |

352 |     type State s a = s -> (a, s)
353 | 
354 |     (>>=) :: State s a -> (a -> State s b) -> State s b
355 |     -- (>>=) :: (s -> (a, s)) -> (a -> s -> (b, s)) -> s -> (b, s)
356 |     f >>= g = 
357 |         -- f :: State s a == s -> (a, s)
358 |         -- g :: a -> State s b == a -> s -> (b, s)
359 |         -- we want to produce a State s b == s -> (b, s)
360 |         \s ->
361 |             let (x, s') = f s
362 |             g x s'
363 | 
364 |     return :: a -> State s a
365 |     -- return :: a -> s -> (a, s)
366 |     return x s = (x, s)
367 | 
368 | 

369 | 370 |

So now I can do:

371 | 372 |

373 |     f :: ... -> State blah something
374 |     f ... =
375 |         ...
376 |         (g ...) >>=
377 |             (\r ->
378 |                 ...
379 |                 return something)
380 | 
381 |     g :: ... -> State blah somethingElse
382 |     g ... blah =
383 |         ...
384 |         (h ...) >>=
385 |             (\r ->
386 |                 ...
387 |                 somethingElse)
388 | 
389 | 

390 | 391 |

HOMEWORK: To make State an abstract type (like we 392 | made Reader), we need three new functions: 393 |

394 |     runState :: State s a -> s -> (a, s)
395 |     get :: State s s
396 |     put :: s -> State s ()
397 | 

398 |

Write these functions. With these funtions, how would you write 399 | h (approximately)?

400 | 401 |

The Monad Typeclass

402 | 403 |

Now we have a problem. We have two definitions (with very similar 404 | types) of the >>= operator:

405 | 406 |

407 |     (>>=) :: Reader r a -> (a -> Reader r b) -> Reader r b
408 |     (>>=) :: State s a -> (a -> State s b) -> State s b
409 | 

410 | 411 |

And two copies of the return function:

412 |

413 |     return :: a -> Reader r a
414 |     return :: a -> State s a
415 | 

416 | 417 |

This causes Haskell to be unhappy. The solution is to introduce a 418 | type class:

419 | 420 |

421 |     class Monad m where
422 |         (>>=) :: m a -> (a -> m b) -> m b
423 |         return :: a -> m a
424 | 

425 | 426 |

Our implementation of Reader would then be:

427 | 428 |

429 |     type Reader r a = r -> a
430 |     instance Monad (Reader r) where
431 |         -- We replace the m with (Reader r), so
432 |         -- m a -> (a -> m b) -> m b
433 |         -- (Reader r) a -> (a -> (Reader r) b) -> (Reader r) b
434 |         -- Reader r a -> (a -> Reader r b) -> Reader r b
435 |         f >>= g = \r -> g (f r) r
436 | 
437 |         -- a -> m a
438 |         -- a -> (Reader r) a
439 |         -- a -> Reader r a
440 |         return x = \_ -> x
441 | 

442 | 443 |

And State would be:

444 |

445 |     type State s a = s -> (a, s)
446 |     instance Monad (State s) where
447 |         f >> g = \s -> let (x, s') = f s in g x s'
448 |         return x = \s -> (x, s)
449 | 

450 | 451 |

HOMEWORK: Is it possible to write the fmap 452 | function using only >>= and return? 453 | What does this mean about the relationship between Functor 454 | and Monad?

455 | 456 |

HOMEWORK: Read up on the Applicative type class- 457 | can it be implemented using only >>= and 458 | return? What does that say about the relationship between 459 | Applicative and Monad?

460 | 461 |

HOMEWORK: The Reader type is "half of" the 462 | State type. Can you implement the "other half"- the 463 | Writer type? How would you deal with the state not being 464 | written, or being written multiple times?

465 | 466 |

A Digression

467 | 468 |

Consider the following code for a moment:

469 |

470 |     instance Monad [] where
471 |         [] >>= _ = []
472 |         (x : xs) >>= f = (f x) ++ (xs >>= f)
473 |         return x = [ x ]
474 | 

475 | 476 |

So lists are monads.

477 | 478 |

HOMEWORK: Can you write similar definitions for 479 | Maybe? How about Either String?

480 | 481 |

Side effects and the IO Type

482 | 483 |

Problem: the only way to guarantee that expression A is evaluated 484 | before expression B is to have expression B depend upon the value 485 | produced by A. But side-effecting computations have ordering dependency 486 | instead of data dependency- we want to print the "password: 487 | " and then read the input line. Many side-effecting 488 | expressions do not even have a sensible data output- OK, 489 | getLine returns a String, but what does 490 | putStr return?

491 | 492 |

Solution: we model the ordering dependency as a "fake" data 493 | dependency. We introduce a special value, of type World# 494 | which represents "the state of the outside world". So now:

495 | 496 |

497 | putStr :: String -> World# -> ((), World#)
498 | getLine :: World# -> (String, World#)
499 | 

500 | 501 |

All side-effecting computations now return at least one peice of 502 | "meaningful" data- the updated state of the world.

503 | 504 |

Problem: Now we need to thread the World# value through 505 | your code. If only there was a way to do that...

506 | 507 |

508 | type IO a = State World# a
509 | 
510 | putStr :: String -> IO ()
511 | getLine :: IO String
512 | 

513 | 514 |

HOMEWORK: Consider the following Haskell program:

515 | 516 |

517 |     main = getLine >>=
518 |             (\line1 ->
519 |                 getLine >>=
520 |                     (\line2 ->
521 |                         putStrLn line1))
522 | 

523 | 524 |

If I run it, and give it the input:

525 | hello
526 | world
527 | 
(note, as two separate lines), what does the program output, and 528 | why? What does a value of the type IO String represent?

529 | 530 |

The Do Notation

531 | 532 |

Problem: continually have to introduce new lambda expressions to bind 533 | the results of monadic computations is a pain. It sure would be nice to 534 | have a "monadic let". And Haskell gives us that with the Do 535 | notation:

536 | 537 |

538 |     main = do
539 |             line1 <- getLine
540 |             line2 <- getLine
541 |             putStrLn line1
542 | 

543 | 544 |

The do notation "desugars" to a sequence of >>= calls and 545 | lambda expressions. So the code:

546 | 547 |

548 |     do
549 |         var <- expr
550 |         ...
551 | 

552 | 553 |

becomes:

554 | 555 |

556 |     expr >>=
557 |         (\var ->
558 |             do
559 |                 ...)
560 | 

561 | 562 |

Likewise,

563 | 564 |

565 |     do
566 |         expr
567 |         ...
568 | 

569 | 570 |

becomes:

571 | 572 |

573 |     expr >>=
574 |         (\ _ ->
575 |             do
576 |                 ...)
577 | 

578 | 579 |

And:

580 | 581 |

582 |     do
583 |         let var = expr
584 |         ...
585 | 

586 | 587 |

(Note the lack of an "in" there!) becomes:

588 | 589 |

590 |     let var = expr in
591 |         do
592 |             ...
593 | 

594 | 595 |

The last statement in a do block is a pure expression which is the 596 | final result. This is normally a return call, but it 597 | can be a control flow expression that itself contains do blocks:

598 | 599 | 600 |

601 | main = do
602 |     putStrLn "What is your guess?"
603 |     guess <- getLine
604 |     -- Now, this is the last statement in this do block
605 |     if ((read guess) == 3::Int) then
606 |         -- Which contains two do blocks inside
607 |         do
608 |             putStrLn "Correct!"
609 |             return ()
610 |     else
611 |         do
612 |             putStrLn "Wrong!"
613 |             main
614 | 

615 | 616 |

HOMEWORK: Rewrite the guessing game example above to 617 | explicitly thread the World# value around (i.e. desugar the 618 | do blocks, inline the definition of >>=). How does 619 | the last call to main work?

620 | 621 |

Monad Transformers

622 | 623 |

So, IO is "impure"- but a lot of the monads we've seen 624 | are pure- State, Reader, Writer, 625 | Maybe, Either, List, and so on. 626 | They do mix fairly promiscuously, and cleanly, with other monads. Can 627 | we express that?

628 | 629 |

630 |     type StateT s m a = s -> m (a, s)
631 | 
632 |     instance Monad m => Monad StateT s m where
633 |         f >>= g = \s -> do
634 |             (x, s') <- f s
635 |             g x s'
636 |         return x s = return (x, s)
637 | 

638 | 639 |

This is the "State Transformer"- it stacks on top of another monad 640 | and threads a state variable through.

641 | 642 |

HOMEWORK: Write the transformer versions of ReaderT, WriterT, 643 | and MaybeT.

644 | 645 |

HOMEWORK: Look up the source code to the standard StateT, 646 | ReaderT, WriterT, and MaybeT implementations on hackage. How does your 647 | code differ from theres? Why did they design their code the way they 648 | did?

649 | 650 |

Monad Laws

651 | 652 |

The three monad laws:

653 |

655 | 656 | 658 | 659 |
1Left Identity:(return x) >>= 654 | f<=>f x
2Right Identity:m >>= 657 | return<=>m
3Associativity:(m >>= f) >>= 660 | g<=>m>>= (\x -> f x 661 | >>= g)

662 | 663 |

The english translation:

664 | 665 |

Rules 1 and 2 mean that the only thing return can do is inject a 666 | value into the monad, it can not perform any other action. Rule 3 says 667 | that the only important thing is the ordering of the bindings. One can 668 | always pull subsequences out into their own values or functions.

669 | 670 |

In other words, the monad laws just mean that the monad 671 | implementation has to behave sensibly.

672 | 673 |

The monad laws also only hold in the lack of bottom (expressions that 674 | throw exceptions, go into infinite loops, exit the program, etc.). 675 | Every so often a debate emerges on the haskell mailing lists over wether 676 | the monad laws are actually followed or not. Rather than participating 677 | in such debates, I recommend reading Fast 679 | and Loose Reasoning is Morally Correct, by Danielsson, Hughes, 680 | Jansso, and Gibbons. Or, better yet, going outside to get some fresh 681 | air and sunshine.

682 | 683 |

HOMEWORK: If you really insist, prove that this implementation 684 | of return for the List monad is incorrect:

685 | 686 |

687 |     return x = [ x, x ]
688 | 

689 | 690 |

HOMEWORK: If you really enjoy this sort of thing, go back and 691 | prove all of our implementations up until this point do, in fact, follow 692 | the monad laws.

693 | 694 |

Designing with Monads

695 | 696 |

In terms of design, a monad is: 697 |

700 | 701 |

There are the operations all monads support (>>=, 702 | return), and operations only supported by specific monads 703 | (get, put, putStrLn, etc.). The 704 | "special abilities" of the monad are in these specific operations.

705 | 706 |

707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 |
MonadSpecial abilities
IOCan do I/O and/or side-effects
StateHas read/write access to a "global variable"
ReaderHas read-only access to a "global variable"
WriterHas write-only access to a "global variable"
MaybeMay not produce an output
ListMay produce multiple outputs

715 | 716 |

In addition, you can define your own monads, either directly, or 717 | using one of the standard monads. For example, you might do:

718 | 719 |

    type WithDBConn a = Reader DB.Conn a

720 | 721 |

To define a monad whose domain is "has a connection to the database". 722 | This is one of the main ways to structure a Haskell program on the large 723 | scale- using monads to define the major "domains" of a program (code 724 | that needs a connection to the database, etc.).

725 | 726 |

HOMEWORK: Think of a program you might want to write. What 727 | are the major domains that program will want? How would you implement 728 | them?

729 | 730 |

The last bit of homework

731 | 732 |

HOMEWORK: Go write Haskell code using monads!

733 | 734 |

FINI

735 | 736 | 737 | -------------------------------------------------------------------------------- /monads.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/monads.odp -------------------------------------------------------------------------------- /notawat.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/notawat.pdf -------------------------------------------------------------------------------- /notawat.tex: -------------------------------------------------------------------------------- 1 | \documentclass{beamer} 2 | 3 | \usetheme{default} 4 | 5 | \title{The Not-A-Wat in Haskell} 6 | \author{Brian Hurt} 7 | \date{18 Oct 2015} 8 | 9 | \begin{document} 10 | 11 | \begin{frame} 12 | \titlepage 13 | \end{frame} 14 | 15 | \begin{frame} 16 | \begin{center}{\tt \Huge }\end{center} 17 | \end{frame} 18 | 19 | \begin{frame} 20 | \frametitle{Wat Definition} 21 | \begin{center}\Large{What is a "Wat"?}\end{center} 22 | \end{frame} 23 | 24 | \begin{frame} 25 | \frametitle{Wat Definition} 26 | \begin{center}\Large{https://www.destroyallsoftware.com/talks/wat}\end{center} 27 | \end{frame} 28 | 29 | \begin{frame} 30 | \frametitle{Wat Definition} 31 | \begin{center} 32 | My definition: 33 | 34 | A "wat" (w.r.t. programming languages) is a behavior that is both 35 | unexpected, and inconsistent with all the other behaviors of the 36 | language. 37 | \end{center} 38 | \end{frame} 39 | 40 | \begin{frame}[fragile] 41 | \frametitle{The Wat In Question} 42 | {\tt \Large{ 43 | Prelude> length (1, 2)\\ 44 | }} 45 | \end{frame} 46 | 47 | \begin{frame}[fragile] 48 | \frametitle{The Wat In Question} 49 | {\tt \Large{ 50 | Prelude> length (1, 2)\\ 51 | 1\\ 52 | Prelude> 53 | }} 54 | \end{frame} 55 | 56 | \begin{frame} 57 | \frametitle{Wat Definition} 58 | \begin{center} 59 | {\Huge This is not a Wat!} 60 | 61 | This behavior is consitent with the rest of the language. 62 | \end{center} 63 | \end{frame} 64 | 65 | \begin{frame}[fragile] 66 | \frametitle{Working Through the Logic} 67 | {\Large 68 | Length gives the number of elements held by a container. 69 | 70 | \vspace{20pt} 71 | 72 | {\tt 73 | Prelude> length [ 1, 2, 3 ]\\ 74 | 3\\ 75 | Prelude> 76 | } 77 | 78 | \vspace{20pt} 79 | 80 | Length just folds over the container, counting the elements as they go by. 81 | } 82 | \end{frame} 83 | 84 | \begin{frame} 85 | \frametitle{Working Through the Logic} 86 | \begin{center} 87 | {\Large 88 | Can you have a container that can \textsl{not} hold an arbitrary number 89 | of elements, but can only hold at most one? 90 | } 91 | \end{center} 92 | \end{frame} 93 | 94 | \begin{frame}[fragile] 95 | \frametitle{Working Through the Logic} 96 | {\Large 97 | {\tt Maybe} works as a "at most one" container: 98 | 99 | \vspace{20pt} 100 | 101 | {\tt 102 | Prelude> length Nothing\\ 103 | 0\\ 104 | Prelude> length (Just "foo")\\ 105 | 1\\ 106 | Prelude> fmap show Nothing\\ 107 | Nothing\\ 108 | Prelude> fmap show (Just 1)\\ 109 | Just "1"\\ 110 | }} 111 | \end{frame} 112 | 113 | 114 | \begin{frame} 115 | \frametitle{Working Through the Logic} 116 | {\Large 117 | You can partially apply multi-param types just like functions. 118 | 119 | So {\tt Either String } works as a "at most one" container: 120 | 121 | {\tt Prelude> foldr (+) 0 (Left "foo") \\ 122 | 0 \\ 123 | Prelude> foldr (+) 0 (Right 2) \\ 124 | 2 \\ 125 | Prelude> fmap show (Right 3) \\ 126 | Right "3" \\ 127 | Prelude> \\ 128 | }} 129 | \end{frame} 130 | 131 | \begin{frame}[fragile] 132 | \frametitle{Working Through the Logic} 133 | {\Large 134 | It is foldable, there for length is defined on it: 135 | 136 | \vspace{32pt} 137 | 138 | {\tt 139 | Prelude> :t length \\ 140 | length :: Foldable t => t a -> Int \\ 141 | Prelude> length (Left "error message") \\ 142 | 0 \\ 143 | Prelude> length (Right 1) \\ 144 | 1 \\ 145 | Prelude> 146 | }} 147 | \end{frame} 148 | 149 | \begin{frame} 150 | \frametitle{Important Concept} 151 | \begin{center} 152 | \textbf{\Huge Tuples} 153 | 154 | \vspace{20pt} 155 | 156 | \textbf{\Huge Are} 157 | 158 | \vspace{20pt} 159 | 160 | \textbf{\Huge Not} 161 | 162 | \vspace{20pt} 163 | 164 | \textbf{\Huge Lists} 165 | 166 | \end{center} 167 | \end{frame} 168 | 169 | \begin{frame} 170 | \frametitle{Important Concept} 171 | {\Large 172 | \begin{itemize} 173 | \item {\tt (,)} is a type, \textbf{just like Either} 174 | \item {\tt (,)} takes two type parameters, \textbf{just like Either} 175 | \item {\tt (,)} as a type can be partially applied, \textbf{just like Either} 176 | \end{itemize} 177 | 178 | \vspace{20pt} 179 | 180 | So, if we apply {\tt (,)} to one type (like we do with Either), what do we get? 181 | } 182 | \end{frame} 183 | 184 | \begin{frame} 185 | \frametitle{Important Concept} 186 | \begin{center} 187 | {\Large 188 | We get a container that holds exactly one value, as the second value of the tuple. 189 | } 190 | \end{center} 191 | \end{frame} 192 | 193 | \begin{frame}[fragile] 194 | \frametitle{Tuples are a Container} 195 | {\Large 196 | {\tt 197 | Prelude> foldr (+) 0 (1, 2) \\ 198 | 2 \\ 199 | Prelude> foldr (+) 0 ("foo", 2) \\ 200 | 2 \\ 201 | Prelude> fmap show (1, 2) \\ 202 | (1,"2") \\ 203 | Prelude> fmap show (False, 2) \\ 204 | (False,"2") \\ 205 | Prelude> length (False, 2) \\ 206 | 1 \\ 207 | Prelude> \\ 208 | }} 209 | \end{frame} 210 | 211 | \begin{frame} 212 | \frametitle{Tuples are a Container} 213 | \begin{center} 214 | What value did you expect {\tt length} to return? 215 | 216 | \vspace{32pt} 217 | 218 | nil? 219 | 220 | \vspace{32pt} 221 | 222 | NaN? 223 | \end{center} 224 | \end{frame} 225 | \begin{frame} 226 | \begin{center}\tt \Huge{}\end{center} 227 | \end{frame} 228 | 229 | 230 | \end{document} 231 | 232 | 233 | 234 | -------------------------------------------------------------------------------- /numhaskell.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/numhaskell.odp -------------------------------------------------------------------------------- /pdre-code/clojure-1.6.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/pdre-code/clojure-1.6.0.jar -------------------------------------------------------------------------------- /pdre-code/jline-0.9.94.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/pdre-code/jline-0.9.94.jar -------------------------------------------------------------------------------- /pdre-code/pdre.clj: -------------------------------------------------------------------------------- 1 | (ns pdre) 2 | 3 | (defmulti is-accepting 4 | "Multimethod- returns true if the given regular expression re is accepting." 5 | first) 6 | 7 | (defmulti is-error 8 | "Multimethod- returns true if the given regular expression re is an error." 9 | first) 10 | 11 | (defmulti deriv 12 | "Multimethod to calculate the derivative of a regular expression re 13 | with respect to the character c." 14 | (fn [ re c ] (first re))) 15 | 16 | (defn re-matches-deriv 17 | "Returns true if s (a string or sequence of characters) matches the 18 | regular expression re." 19 | [ re s ] 20 | (loop [ r re st (seq s) ] 21 | (cond 22 | (is-error r) false 23 | (empty? st) (is-accepting r) 24 | true (recur (deriv r (first st)) (rest st))))) 25 | 26 | (defmethod is-accepting 'error [ re ] false) 27 | (defmethod is-error 'error [ re ] true) 28 | (defmethod deriv 'error [ re c ] '(error)) 29 | 30 | (defmethod is-accepting 'accepting [ re ] true) 31 | (defmethod is-error 'accepting [ re ] false) 32 | (defmethod deriv 'accepting [ re c ] '(error)) 33 | 34 | (defmethod is-accepting 'char [ re ] false) 35 | (defmethod is-error 'char [ re ] false) 36 | (defmethod deriv 'char [ [ _ c ] x ] 37 | (if (= c x) 38 | '(accepting) 39 | '(error))) 40 | 41 | (defmethod is-accepting 'maybe [ re ] true) 42 | (defmethod is-error 'maybe [ [ _ re ] ] false) 43 | (defmethod deriv 'maybe [ [ _ re ] x ] 44 | (deriv re x)) 45 | 46 | (defmethod is-accepting 'zero-or-more [ _ ] true) 47 | (defmethod is-error 'zero-or-more [ _ ] false) 48 | (defmethod deriv 'zero-or-more [ [ _ re ] x ] 49 | (let [ re' (deriv re) ] 50 | (if (is-error re') 51 | '(error) 52 | `(re-seq ~re' (zero-or-more ~re))))) 53 | 54 | (defn- re-union [ re1 re2 ] 55 | (cond 56 | (is-error re1) re2 57 | (is-error re2) re1 58 | true `(or ~re1 ~re2))) 59 | 60 | (defmethod is-accepting 're-seq [ [ _ re1 re2 ] ] 61 | (and (is-accepting re1) (is-accepting re2))) 62 | (defmethod is-error 're-seq [ [ _ re1 re2 ] ] 63 | (or (is-error re1) (is-error re2))) 64 | (defmethod deriv 're-seq [ [ _ re1 re2 ] x ] 65 | (if (is-accepting re1) 66 | (re-union 67 | `(re-seq ~(deriv re1 x) ~re2) 68 | (deriv re2 x)) 69 | (let [ re1' (deriv re1 x) ] 70 | (if (is-error re1') 71 | '(error) 72 | `(re-seq ~re1 ~re2))))) 73 | 74 | (defmethod is-accepting 'or [ [ _ re1 re2 ] ] 75 | (or (is-accepting re1) (is-accepting re2))) 76 | (defmethod is-error 'or [ [ _ re1 re2 ] ] 77 | (and (is-error re1) (is-error re2))) 78 | (defmethod deriv 'or [ [ _ re1 re2 ] x ] 79 | (re-union (deriv re1 x) (deriv re2 x))) 80 | 81 | (defn re-intersection [ re1 re2 ] 82 | (if (or (is-error re1) (is-error re2)) 83 | '(error) 84 | `(and ~re1 ~re2))) 85 | 86 | (defmethod is-accepting 'and [ [ _ re1 re2 ] ] 87 | (and (is-accepting re1) (is-accepting re2))) 88 | (defmethod is-error 'and [ [ _ re1 re2 ] ] 89 | (or (is-error re1) (is-error re2))) 90 | (defmethod deriv 'and [ [ _ re1 re2 ] x ] 91 | (re-intersection (deriv re1 x) (deriv re2 x))) 92 | 93 | (defmethod deriv 'not [ [ _ re ] x ] 94 | `(not (deriv re x))) 95 | (defmethod is-accepting 'not [ [ _ re ] ] 96 | (not (is-accepting re))) 97 | (defmethod is-error 'not [ [ _ re ] ] false) 98 | 99 | (def ^:dynamic max-state nil) 100 | (def ^:dynamic state-to-idx nil) 101 | (def ^:dynamic idx-to-state nil) 102 | (def ^:dynamic accepting-states nil) 103 | 104 | (defn- make-state [ re' ] 105 | (let [ idx' (swap! max-state inc) ] 106 | (swap! state-to-idx assoc re' idx') 107 | (swap! idx-to-state assoc idx' re') 108 | idx')) 109 | 110 | (defn- make-trans [ re ] 111 | (into-array Integer/TYPE 112 | (for [ c (map char (range 0 127)) ] 113 | (let [ re' (deriv re c) ] 114 | (if (is-error re') 115 | -1 116 | (or 117 | (get @state-to-idx re') 118 | (make-state re'))))))) 119 | 120 | (defn- make-states [ idx ] 121 | (when (<= idx @max-state) 122 | (let [ re (get @idx-to-state idx) 123 | trans (make-trans re) ] 124 | (when (is-accepting re) 125 | (swap! accepting-states conj idx)) 126 | (cons trans (make-state (inc idx)))))) 127 | 128 | (defn make-dfa [ re ] 129 | (binding [ max-state (atom 0) 130 | state-to-idx (atom { re 0 }) 131 | idx-to-state (atom { 0 re }) 132 | accepting-states (atom #{}) ] 133 | (let [ table (into-array (make-states 0)) ] 134 | [ table @accepting-states ]))) 135 | 136 | (defn dfa-matches [ dfa s ] 137 | (let [ [ table accpts ] dfa ] 138 | (loop [ state 0 st s ] 139 | (cond 140 | (= state -1) false 141 | (empty? st) 142 | (boolean (accpts state)) 143 | true 144 | (recur 145 | (aget (aget table state) 146 | (int (first st))) 147 | (rest st)))))) 148 | 149 | -------------------------------------------------------------------------------- /pdre-code/repl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | java -server -cp .:./classes:./lib/*:./* -XX:MaxPermSize=160m -XX:-DontCompileHugeMethods -Xmx256m -Xincgc -Xshare:off -Xbootclasspath/a:jline.ConsoleRunner -Xbootclasspath/a:clojure.main jline.ConsoleRunner clojure.main 3 | 4 | -------------------------------------------------------------------------------- /pdre.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/pdre.odp -------------------------------------------------------------------------------- /pdrehs.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/pdrehs.odp -------------------------------------------------------------------------------- /statictyping.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/statictyping.odp -------------------------------------------------------------------------------- /types.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/types.odp -------------------------------------------------------------------------------- /types.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/types.pdf -------------------------------------------------------------------------------- /types.tex: -------------------------------------------------------------------------------- 1 | \documentclass{beamer} 2 | 3 | \usetheme{default} 4 | 5 | \title{Introduction to Type Inference} 6 | \author{Brian Hurt} 7 | \date{22 April 2015} 8 | 9 | \begin{document} 10 | 11 | \begin{frame} 12 | \titlepage 13 | \end{frame} 14 | 15 | \begin{frame} 16 | \frametitle{Why you care} 17 | \begin{itemize} 18 | \item Forms the basis for most static type systems (Haskell, Ocaml, Scala, Swift, etc.) 19 | \item Increasingly used in optional type systems (Typed Racket, Clojure's 20 | core.typed, C++'s auto, static analysis tools like Coverity, etc.) 21 | \item The basis for more advanced type system features 22 | \item Helps in understanding otherwise cryptic error messages 23 | \end{itemize} 24 | 25 | \end{frame} 26 | 27 | \begin{frame} 28 | \frametitle{What this talk does} 29 | \begin{itemize} 30 | \item Introduces a simple subset of Haskell called SiML 31 | \item Creates a type inference/type checking algorithm for it 32 | \item Concurrently introduces the notation used by the research (the 33 | ``Natural Deduction Style'') 34 | \end{itemize} 35 | 36 | This code is not how GHC really works, however... 37 | \end{frame} 38 | 39 | \begin{frame} 40 | \frametitle{Technobabble} 41 | \begin{center} 42 | SiML is an enriched lambda caculus on which we perform a modified and 43 | simplified Hindley-Milner-Damas algorithm. 44 | \end{center} 45 | \end{frame} 46 | 47 | \begin{frame}[fragile] 48 | \frametitle{The SiML Language} 49 | {\tt \Large{ 50 | \begin{verbatim} 51 | data Expr a = 52 | Const Const 53 | | Var Var 54 | | If (Expr a) (Expr a) (Expr a) 55 | | Apply (Expr a) (Expr a) 56 | | Lambda Var (Expr a) 57 | | Let Var (Expr a) (Expr a) 58 | | LetRec [ (Var, (Expr a)) ] 59 | (Expr a) 60 | | Typed (Expr a) (Type a) 61 | deriving (Read, Show, Eq, Ord) 62 | \end{verbatim} 63 | }} 64 | \end{frame} 65 | 66 | 67 | \begin{frame}[fragile] 68 | \frametitle{The SiML Language} 69 | {\tt \Large{ 70 | \begin{verbatim} 71 | instance Functor Expr where ... 72 | 73 | instance Foldable Expr where ... 74 | \end{verbatim} 75 | }} 76 | \end{frame} 77 | 78 | \begin{frame}[fragile] 79 | \frametitle{The SiML Language} 80 | {\tt \Large{ 81 | \begin{verbatim} 82 | type Var = String 83 | 84 | data Const = 85 | ConstInt Integer 86 | | ConstBool Bool 87 | deriving (Read, Show, Eq, Ord) 88 | \end{verbatim} 89 | }} 90 | \end{frame} 91 | 92 | \begin{frame}[fragile] 93 | \frametitle{The SiML Language} 94 | {\tt \Large{ 95 | \begin{verbatim} 96 | data Type a = 97 | TBool 98 | | TInt 99 | | TFun Type Type 100 | | TVar a 101 | deriving (Read, Show, Eq, Ord) 102 | 103 | instance Functor Type where ... 104 | 105 | instance Foldable Type where ... 106 | 107 | \end{verbatim} 108 | }} 109 | \end{frame} 110 | 111 | \begin{frame}[fragile] 112 | \frametitle{The SiML Language} 113 | {\tt\Large{ 114 | \begin{verbatim} 115 | data Stmnt = 116 | LetStmnt Var Expr 117 | | LetRecStmnt [ (Var, Expr) ] 118 | \end{verbatim} 119 | }} 120 | \end{frame} 121 | 122 | \begin{frame} 123 | \frametitle{Basic Intuition} 124 | \begin{center} 125 | \huge{ 126 | The basic intuition: 127 | 128 | \vspace{20pt} 129 | The structure of the code itself imposes constraints on the types. 130 | 131 | \vspace{20pt} 132 | We can use these constraints to determine the type. 133 | } 134 | \end{center} 135 | \end{frame} 136 | 137 | \begin{frame} 138 | \frametitle{Basic Intuition} 139 | \begin{center} 140 | \huge{ 141 | For example, given: 142 | 143 | $$\text{if}\hspace{5pt}e_1\hspace{5pt}\text{then}\hspace{5pt}e_2 144 | \hspace{5pt}\text{else}\hspace{5pt}e_3$$ 145 | 146 | Where: 147 | $$e_1:t_1\qquad{}e_2:t_2\qquad{}e_3:t_3$$} 148 | \end{center} 149 | \end{frame} 150 | 151 | \begin{frame} 152 | \frametitle{Basic Intuition} 153 | \begin{center} 154 | \huge{ 155 | Then we know that: 156 | 157 | $$t_1 = Bool$$ 158 | 159 | $$t_2 = t_3 = \text{type of the if statement}$$} 160 | \end{center} 161 | \end{frame} 162 | 163 | 164 | \begin{frame} 165 | \frametitle{Natural Deduction Style} 166 | \begin{center} 167 | \huge{ 168 | The ``natural deduction style'' of logical systems. 169 | } 170 | \end{center} 171 | \end{frame} 172 | 173 | \begin{frame} 174 | \frametitle{Natural Deduction Style} 175 | \Huge{ 176 | $$\frac{\Gamma,x:t_1\dashv{}e:t_2}{\Gamma\dashv{}\lambda{}x.e:t_1\rightarrow{}t_2}$$ 177 | } 178 | \end{frame} 179 | 180 | \begin{frame} 181 | \frametitle{Natural Deduction Style} 182 | \begin{center} 183 | \Huge{ 184 | Don't Panic 185 | } 186 | \end{center} 187 | \end{frame} 188 | 189 | \begin{frame} 190 | \frametitle{Natural Deduction Style} 191 | \huge{ 192 | $$\frac{\text{If this is true}}{\text{Then this is true}}$$ 193 | } 194 | \end{frame} 195 | 196 | \begin{frame} 197 | \frametitle{Natural Deduction Style} 198 | \Large{ 199 | $$\frac{e_1:t_1\quad{}e_2:t_2\quad{}e_3:t_3\quad{}t_1 = \text{Bool}\quad{}t_2 = t\quad{}t_3 = t}{ 200 | (\text{if}\hspace{5pt}e_1\hspace{5pt}\text{then}\hspace{5pt}e_2 201 | \hspace{5pt}\text{else}\hspace{5pt}e_3):t}$$ 202 | } 203 | \end{frame} 204 | 205 | \begin{frame} 206 | \frametitle{Type Unification} 207 | \begin{center} 208 | \Huge{ 209 | What is meant by: 210 | 211 | $$t_1 = t_2$$ 212 | } 213 | \end{center} 214 | \end{frame} 215 | 216 | \begin{frame} 217 | \frametitle{Type Unification} 218 | \begin{center} 219 | \Huge{ 220 | The mathematician means: 221 | 222 | \vspace{40pt} 223 | 224 | You can replace all occurrences of $t_1$ with $t_2$. 225 | } 226 | \end{center} 227 | \end{frame} 228 | 229 | \begin{frame} 230 | \frametitle{Type Unification} 231 | \Large{ 232 | So you can replace $t_1$ with Bool, and $t_2$ and $t_3$ with $t$: 233 | 234 | $$\frac{e_1:\text{Bool}\qquad{}e_2:t\qquad{}e_3:t}{ 235 | (\text{if}\hspace{5pt}e_1\hspace{5pt}\text{then}\hspace{5pt}e_2 236 | \hspace{5pt}\text{else}\hspace{5pt}e_3):t}$$ 237 | } 238 | \end{frame} 239 | 240 | \begin{frame} 241 | \frametitle{Type Unification} 242 | \begin{center} 243 | \Huge{ 244 | The programmer means: 245 | 246 | \vspace{40pt} 247 | 248 | Change the state of the system so that $t_1 = t_2$. 249 | } 250 | \end{center} 251 | \end{frame} 252 | 253 | \begin{frame}[fragile] 254 | \frametitle{Type Unification} 255 | 256 | {\tt\large{ 257 | \begin{verbatim} 258 | type Matching a = ... 259 | 260 | instance Monad Matching where 261 | ... 262 | 263 | unify :: Type Var -> Type Var 264 | -> Matching (Type Var) 265 | unify = undefined 266 | \end{verbatim} 267 | 268 | So $t_1 = t_2$ becomes {\tt unify t1 t2}. 269 | }} 270 | \end{frame} 271 | 272 | \begin{frame}[fragile] 273 | \frametitle{Type Inference: If } 274 | 275 | {\tt\large{ 276 | \begin{verbatim} 277 | typeInfer :: Expr Var 278 | -> Matching (Type Var) 279 | 280 | typeInfer (If e1 e2 e3) = do 281 | t1 <- typeInfer e1 282 | t2 <- typeInfer e2 283 | t3 <- typeInfer e3 284 | _ <- unify t1 TBool 285 | unify t2 t3 286 | \end{verbatim} 287 | }} 288 | \end{frame} 289 | 290 | \begin{frame} 291 | \frametitle{Type Inference: Constants} 292 | \Large{ 293 | Integer and boolean constants have their obvious types. 294 | 295 | $$\frac{}{\text{True}:\text{Bool}\qquad{}\text{False}:\text{Bool}}$$ 296 | 297 | \vspace{40pt} 298 | 299 | $$\frac{}{0:\text{Int}\quad{}1:\text{Int}\quad{}...}$$ 300 | } 301 | \end{frame} 302 | 303 | \begin{frame}[fragile] 304 | \frametitle{Type Inference: Constants} 305 | 306 | {\tt\large{ 307 | \begin{verbatim} 308 | typeInfer (Const (ConstInt _)) = 309 | return TInt 310 | typeInfer (Const (ConstBool _)) = 311 | return TBool 312 | \end{verbatim} 313 | }} 314 | \end{frame} 315 | 316 | \begin{frame} 317 | \frametitle{Type Inference: Constants} 318 | \Large{ 319 | Type application is also obvious: 320 | 321 | $$\frac{f:t_1 \rightarrow{} t_2\qquad{}x:t_1}{(f\hspace{5pt}x):t_2}$$ 322 | } 323 | \end{frame} 324 | 325 | \begin{frame}[fragile] 326 | \frametitle{Type Inference: Application} 327 | 328 | \Large{ 329 | {\tt 330 | \begin{verbatim} 331 | typeInfer (Apply f x) = do 332 | tf <- typeInfer f 333 | tx <- typeInfer x 334 | case tf of 335 | TFun t1 t2 -> do 336 | _ <- unify t1 tx 337 | return t2 338 | _ -> fail "Not a function!" 339 | \end{verbatim} 340 | }} 341 | \end{frame} 342 | 343 | \begin{frame} 344 | \frametitle{Type Inference: Typed Expressions} 345 | \Large{ 346 | 347 | Typed expressions are also obvious: 348 | 349 | $$\frac{x:t}{(x\hspace{5pt}::\hspace{5pt}t):t}$$ 350 | } 351 | \end{frame} 352 | 353 | \begin{frame}[fragile] 354 | \frametitle{Type Inference: Typed Expressions} 355 | 356 | \Large{ 357 | {\tt 358 | \begin{verbatim} 359 | typeInfer (Typed x t) = do 360 | tx <- typeInfer x 361 | unify tx t 362 | \end{verbatim} 363 | }} 364 | \end{frame} 365 | 366 | \begin{frame}[fragile] 367 | \frametitle{Type Inference: Var and Let} 368 | 369 | Consider... 370 | 371 | {\tt\large{ 372 | \begin{verbatim} 373 | typeInfer (Var x) = ... 374 | typeInfer (Let x e1 e2) = ... 375 | \end{verbatim} 376 | }} 377 | \end{frame} 378 | 379 | \begin{frame} 380 | \frametitle{Type Inference: Var and Let} 381 | \begin{center} 382 | \Large{ 383 | We need to pass around a map of variables to their types. 384 | } 385 | \end{center} 386 | \end{frame} 387 | 388 | \begin{frame}[fragile] 389 | \frametitle{Type Inference: Var and Let} 390 | 391 | {\tt\large{ 392 | \begin{verbatim} 393 | typeInfer :: [ (Var, Type Var) ] 394 | -> Expr Var 395 | -> Matching (Type Var) 396 | 397 | typeInfer ctx (Var x) = 398 | case (lookup x ctx) of 399 | Just t -> return t 400 | Nothing -> fail "Unknown variable" 401 | 402 | typeInfer ctx (Let x e1 e2) = do 403 | t1 <- typeInfer ctx e1 404 | typeInfer ((x, t1) : ctx) e2 405 | \end{verbatim} 406 | }} 407 | \end{frame} 408 | 409 | 410 | \begin{frame}[fragile] 411 | \frametitle{Type Inference: If and Constants (v2.0)} 412 | 413 | {\tt\large{ 414 | \begin{verbatim} 415 | typeInfer ctx (If e1 e2 e3) = do 416 | t1 <- typeInfer ctx e1 417 | t2 <- typeInfer ctx e2 418 | t3 <- typeInfer ctx e3 419 | _ <- unify t1 TBool 420 | unify t2 t3 421 | typeInfer _ (Const (ConstInt _)) = 422 | return TInt 423 | typeInfer _ (Const (ConstBool _)) = 424 | return TBool 425 | \end{verbatim} 426 | }} 427 | \end{frame} 428 | 429 | \begin{frame} 430 | \frametitle{Natural Deduction Style: Contexts} 431 | We use $\Gamma$ to represent our context, and $\dashv$ to mean ``evaluate 432 | the right hand side with the context on the left'': 433 | 434 | \LARGE{ 435 | $$\frac{\Gamma\dashv{}e_1:Bool\qquad\Gamma\dashv{}e_2:t\qquad\Gamma\dashv{}e_3:t}{\Gamma\dashv{}(\text{if}\hspace{5pt}e_1\hspace{5pt}\text{then}\hspace{5pt}e_2 436 | \hspace{5pt}\text{else}\hspace{5pt}e_3):t}$$ 437 | } 438 | \end{frame} 439 | 440 | \begin{frame} 441 | \frametitle{Natural Deduction Style: Contexts} 442 | \LARGE{ 443 | $$\frac{x:t \in{} \Gamma}{\Gamma{}\dashv{}x:t}$$ 444 | 445 | \vspace{20pt} 446 | 447 | $$\frac{\Gamma\dashv{}e_1:t_1\qquad{}\Gamma{},x:t_1\dashv{}e_2:t_2}{\Gamma\dashv{}(\text{let}\hspace{5pt}x=e_1\hspace{5pt}\text{in}\hspace{5pt}e2):t_2}$$ 448 | } 449 | \end{frame} 450 | 451 | \begin{frame} 452 | \frametitle{Type Inference: Lambda} 453 | \begin{center} 454 | \Large{ 455 | This works great for let (where we know the value being bound, and therefor 456 | the type). 457 | 458 | \vspace{20pt} 459 | 460 | But what about lambda?} 461 | \end{center} 462 | \end{frame} 463 | 464 | \begin{frame}[fragile] 465 | \frametitle{Type Inference: Lambda} 466 | \Large{ 467 | We need to know the type of the argument before we can infer the 468 | type of the body- except it's how the argument is used which 469 | determines it's type! For example: 470 | 471 | \tt 472 | \begin{verbatim} 473 | (\x -> x + 1) 474 | \end{verbatim} 475 | } 476 | \end{frame} 477 | 478 | \begin{frame} 479 | \frametitle{Type Inference: Lambda} 480 | 481 | \Large{ 482 | With math, we can just assume it exists: 483 | 484 | $$\frac{\Gamma,x:t_1\dashv{}e:t_2}{\Gamma\dashv{}(\lambda{}x.e):t_1 \rightarrow{} t_2}$$ 485 | 486 | \vspace{20pt} 487 | 488 | With code, we can't pull this stunt. 489 | } 490 | \end{frame} 491 | 492 | \begin{frame}[fragile] 493 | \frametitle{Type Inference: Lambda} 494 | 495 | {\tt\Large{ 496 | \begin{verbatim} 497 | typeInfer ctx (Lambda x e) = do 498 | t1 <- what goes here? 499 | t2 <- typeInfer ((x, t1) : ctx) e 500 | return (TFun t1 t2) 501 | \end{verbatim} 502 | }} 503 | \end{frame} 504 | 505 | \begin{frame} 506 | \frametitle{Type Inference: Lambda} 507 | By the way, does this expression look familiar? 508 | 509 | {\Huge 510 | $$\frac{\Gamma,x:t_1\dashv{}e:t_2}{\Gamma\dashv{}\lambda{}x.e:t_1\rightarrow{}t_2}$$ 511 | } 512 | 513 | \vspace{40pt} 514 | 515 | (hint: Don't Panic) 516 | \end{frame} 517 | 518 | \begin{frame} 519 | \frametitle{Type Variables} 520 | \begin{center} 521 | \Huge{ 522 | The Two Types of 523 | 524 | Type Variables 525 | } 526 | \end{center} 527 | \end{frame} 528 | 529 | \begin{frame} 530 | \frametitle{Type Variables: Universal} 531 | \Large{ 532 | \begin{definition} 533 | A \alert{universal} type variable can be any type. 534 | 535 | Also known as: rigid type variables, skolem type variables. 536 | \end{definition} 537 | } 538 | \end{frame} 539 | 540 | \begin{frame}[fragile] 541 | \frametitle{Type Variables: Universal} 542 | \Large{ 543 | \begin{center} 544 | Universal type variables are the ``normal'' type variables: 545 | \end{center} 546 | 547 | {\tt 548 | \begin{verbatim} 549 | map :: (a -> b) -> [a] -> [b] 550 | \end{verbatim} 551 | } 552 | 553 | } 554 | \end{frame} 555 | 556 | \begin{frame} 557 | \frametitle{Type Variables: Existential} 558 | \Large{ 559 | \begin{definition} 560 | A \alert{existential} type variable represents a specific type that is 561 | not yet known. The type is known when the type variable is unified with 562 | some other type. 563 | 564 | Also known as: flexible type variables. 565 | 566 | \end{definition} 567 | } 568 | \end{frame} 569 | 570 | \begin{frame}[fragile] 571 | \frametitle{Type Variables: Universal} 572 | \large{ 573 | \begin{center} 574 | You don't see existential type variables in Haskell, but other languages 575 | do display them: 576 | \end{center} 577 | 578 | {\tt 579 | \begin{verbatim} 580 | > ocaml 581 | OCaml version 4.01.0 582 | 583 | # let r = ref None;; 584 | val r : '_a option ref = {contents = None} 585 | # r := Some 1;; 586 | - : unit = () 587 | # r;; 588 | - : int option ref = {contents = Some 1} 589 | # 590 | \end{verbatim} 591 | } 592 | 593 | } 594 | \end{frame} 595 | 596 | \begin{frame} 597 | \frametitle{Type Variables} 598 | \Large{ 599 | \alert{Universal} type variable: this type could be any type in the 600 | whole wide \alert{universe}. 601 | 602 | \vspace{40pt} 603 | 604 | \alert{Existential} type variable: this type \alert{exist}s, but we 605 | don't know what it is yet. 606 | } 607 | \end{frame} 608 | 609 | \begin{frame}[fragile] 610 | \frametitle{Type Inference: Lambda} 611 | 612 | \Large{ 613 | \begin{center} 614 | Existential type variables solve our Lambda problem. 615 | \end{center} 616 | 617 | {\tt 618 | \begin{verbatim} 619 | typeInfer ctx (Lambda x e) = do 620 | t1 <- allocExistVar 621 | t2 <- typeInfer ((x, t1) : ctx) e 622 | return (TFun t1 t2) 623 | \end{verbatim} 624 | }} 625 | \end{frame} 626 | 627 | \begin{frame}[fragile] 628 | \frametitle{Type Inference: Lambda} 629 | 630 | Of course, this requires some type signature changes: 631 | 632 | {\tt 633 | \begin{verbatim} 634 | type EVar = ... 635 | 636 | type TVar = Either Var EVar 637 | 638 | allocExistVar :: Matching (Type TVar) 639 | allocExistVar = undefined 640 | 641 | unify :: Type TVar -> Type TVar 642 | -> Matching (Type TVar) 643 | unify = undefined 644 | 645 | typeInfer :: [ (Var, Type TVar) ] 646 | -> Expr Var 647 | -> Matching TVar 648 | ... 649 | \end{verbatim} 650 | } 651 | \end{frame} 652 | 653 | \begin{frame}[fragile] 654 | \frametitle{Type Inference: Lambda} 655 | 656 | Existential type variables also solves the problem with let rec: 657 | 658 | {\tt 659 | \begin{verbatim} 660 | typeInfer ctx (LetRec defns e) = do 661 | ts <- mapM getEVar defns 662 | let ctx' = ts ++ ctx 663 | mapM_ (inferBody ctx') defns 664 | typeInfer ctx' e 665 | where 666 | getEVar (v, _) = do 667 | t <- allocExistVar 668 | return (v, t) 669 | inferBody c (_, e1) = 670 | typeInfer c e1 671 | \end{verbatim} 672 | } 673 | \end{frame} 674 | 675 | \begin{frame} 676 | \frametitle{Type Variables: Two Problems} 677 | \Huge{ 678 | \begin{center} 679 | Two Problems 680 | \end{center} 681 | } 682 | \end{frame} 683 | 684 | \begin{frame} 685 | \frametitle{Type Variables: Problem 1: Typed Expressions} 686 | \Large{ 687 | \begin{center} 688 | With Typed expressions, the AST gives us {\tt Type Var}, but we 689 | need {\tt Type TVar} to pass in to unify. 690 | 691 | \vspace{40pt} 692 | 693 | Note: the types given in the AST can only contain universal type 694 | variables! 695 | \end{center} 696 | } 697 | \end{frame} 698 | 699 | \begin{frame}[fragile] 700 | \frametitle{Type Variables: Problem 1: Typed Expressions} 701 | 702 | \Large{ 703 | Using {\tt fmap Left} converts a {\tt Type Var} into a 704 | {\tt Type TVar} (making all variables universal): 705 | 706 | {\tt 707 | \begin{verbatim} 708 | typeInfer (Typed x t) = do 709 | tx <- typeInfer x 710 | unify tx (fmap Left t) 711 | \end{verbatim} 712 | }} 713 | \end{frame} 714 | 715 | \begin{frame}[fragile] 716 | \frametitle{Type Variables: Problem 2: Using Variables} 717 | \Large{ 718 | Consider map: 719 | 720 | {\tt 721 | \begin{verbatim} 722 | map :: (a -> b) -> [a] -> [b] 723 | \end{verbatim} 724 | } 725 | 726 | \vspace{20pt} 727 | 728 | \alert{Inside} map, {\tt a} and {\tt b} are universal type variables, and 729 | can not be unified with any other type. 730 | 731 | \vspace{20pt} 732 | 733 | But when we \alert{call} map, they can be any type we want. 734 | } 735 | \end{frame} 736 | 737 | \begin{frame}[fragile] 738 | \frametitle{Type Variables: Problem 2: Using Variables} 739 | \Large{ 740 | \begin{center} 741 | When we use a variable whose type has universal type variables, the 742 | universal type variables need to be converted into existential type 743 | variables. 744 | 745 | \vspace{20pt} 746 | 747 | But, all instances of the same universal type variable need to map 748 | to the same existential type variable. 749 | \end{center} 750 | } 751 | \end{frame} 752 | 753 | \begin{frame}[fragile] 754 | \frametitle{Type Variables: Problem 2: Using Variables} 755 | 756 | {\tt 757 | \begin{verbatim} 758 | import Data.List(nub) 759 | import Data.Foldable(toList) 760 | import Data.Maybe(fromJust) 761 | 762 | typeInfer ctx (Var x) = 763 | case (lookup x ctx) of 764 | Just t -> do 765 | let uvars = nub (toList t) 766 | evars <- mapM (const allocExistVar) 767 | uvars 768 | let varMap = zip uvars evars 769 | return (fmap (fixVar varMap) t) 770 | Nothing -> fail "Unknown variable" 771 | where 772 | fixVar varMap v = 773 | fromJust (lookup v varMap) 774 | \end{verbatim} 775 | } 776 | \end{frame} 777 | 778 | \begin{frame} 779 | \frametitle{Unify} 780 | \Huge{ 781 | \begin{center} 782 | Unify 783 | \end{center} 784 | } 785 | \end{frame} 786 | 787 | 788 | \begin{frame}[fragile] 789 | \frametitle{Unify} 790 | 791 | \Large{\tt 792 | \begin{verbatim} 793 | data Type a = 794 | TBool 795 | | TInt 796 | | TFun Type Type 797 | | TVar a 798 | 799 | unify :: Type TVar -> Type TVar 800 | -> Matching (Type TVar) 801 | unify = undefined 802 | \end{verbatim} 803 | } 804 | \end{frame} 805 | 806 | \begin{frame}[fragile] 807 | \frametitle{Unify} 808 | 809 | \Large{ 810 | 811 | The easy cases: 812 | 813 | {\tt 814 | \begin{verbatim} 815 | unify TBool TBool = return TBool 816 | unify TInt TInt = return TInt 817 | \end{verbatim} 818 | }} 819 | \end{frame} 820 | 821 | \begin{frame}[fragile] 822 | \frametitle{Unify} 823 | \large{ 824 | \begin{center} 825 | $$t_1 \rightarrow{} t_2 = t_3 \rightarrow{} t_4$$ 826 | implies: 827 | $$t_1 = t_3\qquad{}\&\&\qquad{}t_2 = t_4$$ 828 | \end{center} 829 | 830 | {\tt 831 | \begin{verbatim} 832 | unify (TFun t1 t2) (TFun t3 t4) = do 833 | t5 <- unify t1 t3 834 | t6 <- unify t2 t4 835 | return (TFun t5 t6) 836 | \end{verbatim} 837 | }} 838 | \end{frame} 839 | 840 | 841 | \begin{frame}[fragile] 842 | \frametitle{Unify} 843 | \large{ 844 | \begin{center} 845 | Two universal type variables only unify if they're the same type 846 | variable. 847 | \end{center} 848 | 849 | {\tt 850 | \begin{verbatim} 851 | unify (TVar (Left a)) (TVar (Left b)) 852 | | a == b = return (TVar (Left a)) 853 | | otherwise = fail "Type error" 854 | \end{verbatim} 855 | }} 856 | \end{frame} 857 | 858 | \begin{frame} 859 | \frametitle{Unify} 860 | \Large{ 861 | \begin{center} 862 | Interesting Question: 863 | 864 | \vspace{20pt} 865 | 866 | What is the scope of a universal type variable? That is: when does one 867 | {\tt a} in one type expression match represent the same (polymorphic) 868 | type as another {\tt a} in some other type expression? 869 | \end{center} 870 | } 871 | \end{frame} 872 | 873 | 874 | \begin{frame} 875 | \frametitle{Unify: Existential Types} 876 | \Huge{ 877 | \begin{center} 878 | Existential Types 879 | \end{center} 880 | } 881 | \end{frame} 882 | 883 | \begin{frame} 884 | \frametitle{Unify: Existential Types} 885 | The rules for unifying existential types are: 886 | \begin{itemize} 887 | \item Existential type variables can be assigned another type \alert{at 888 | most once}. 889 | \item If an existential type variablehas been assigned another type 890 | previously, we unify with that type instead. 891 | \item Otherwise, we assign the other type to the existential type variable. 892 | \item It is possible for both types to be existential type variables 893 | which have not been assigned previously, in which case we assign one 894 | to the other. 895 | \end{itemize} 896 | \end{frame} 897 | 898 | \begin{frame}[fragile] 899 | \frametitle{Unify: Existential Types} 900 | \large{ 901 | We need some way to set an existential type variable to a given type: 902 | {\tt 903 | \begin{verbatim} 904 | setEVar :: EVar -> Type TVar -> Matching () 905 | setEVar = undefined 906 | \end{verbatim} 907 | } 908 | 909 | And we need a way to get the value it was set to (if it was set 910 | previously): 911 | 912 | {\tt 913 | \begin{verbatim} 914 | getEVar :: EVar -> Matching (Maybe (Type TVar)) 915 | getEVar = undefined 916 | \end{verbatim} 917 | } 918 | } 919 | \end{frame} 920 | 921 | \begin{frame}[fragile] 922 | \frametitle{Unify: Existential Types} 923 | \large{ 924 | {\tt 925 | \begin{verbatim} 926 | unify (TVar (Right a)) t2 = do 927 | mt1 <- getEVar a 928 | case mt1 of 929 | Some t1 -> unify t1 t2 930 | None -> do 931 | setEVar a t2 932 | return t2 933 | \end{verbatim} 934 | }} 935 | \end{frame} 936 | 937 | \begin{frame}[fragile] 938 | \frametitle{Unify: Existential Types} 939 | \large{ 940 | {\tt 941 | \begin{verbatim} 942 | unify t1 (TVar (Right b)) = do 943 | mt2 <- getEVar b 944 | case mt2 of 945 | Some t2 -> unify t1 t2 946 | None -> do 947 | setEVar b t1 948 | return t1 949 | \end{verbatim} 950 | }} 951 | \end{frame} 952 | 953 | \begin{frame}[fragile] 954 | \frametitle{Unify: Existential Types} 955 | \large{ 956 | \begin{center} 957 | \alert{All} other patterns are type errors! 958 | \end{center} 959 | 960 | {\tt 961 | \begin{verbatim} 962 | unify _ _ = fail "Type error" 963 | \end{verbatim} 964 | }} 965 | \end{frame} 966 | 967 | \begin{frame}[fragile] 968 | \frametitle{Unify: Matching Utils} 969 | \large{ 970 | {\tt 971 | \begin{verbatim} 972 | import Data.Default 973 | 974 | type EVar = Int 975 | 976 | data MState = MState { 977 | evarCounter :: Int, 978 | evarMappings :: [ (EVar, Type TVar) ] 979 | } 980 | 981 | type Matching a = State MState a 982 | 983 | instance Default MState where 984 | def = MState 0 [] 985 | \end{verbatim} 986 | }} 987 | \end{frame} 988 | 989 | \begin{frame}[fragile] 990 | \frametitle{Unify: Matching Utils} 991 | \large{ 992 | {\tt 993 | \begin{verbatim} 994 | allocExistVar :: Matching (Type TVar) 995 | allocExistVar = do 996 | mstate <- get 997 | let evar = evarCounter mstate 998 | put (mstate { evarCounter = evar + 1 }) 999 | return (Type (Right evar)) 1000 | \end{verbatim} 1001 | }} 1002 | \end{frame} 1003 | 1004 | \begin{frame}[fragile] 1005 | \frametitle{Unify: Matching Utils} 1006 | \large{ 1007 | {\tt 1008 | \begin{verbatim} 1009 | setEVar :: EVar -> Type TVar -> Matching () 1010 | setEVar evar typ = do 1011 | mstate <- get 1012 | let mappings = 1013 | (evar, typ) : evarMappings mstate 1014 | put (mstate { evarMappings = mappings }) 1015 | \end{verbatim} 1016 | }} 1017 | \end{frame} 1018 | 1019 | \begin{frame}[fragile] 1020 | \frametitle{Unify: Matching Utils} 1021 | \large{ 1022 | {\tt 1023 | \begin{verbatim} 1024 | getEVar :: EVar -> Matching (Maybe (Type TVar)) 1025 | getEVar evar = do 1026 | mstate <- get 1027 | let mappings = evarMappings mstate 1028 | return (lookup evar mappings) 1029 | \end{verbatim} 1030 | }} 1031 | \end{frame} 1032 | 1033 | \begin{frame} 1034 | \frametitle{One Last Problem} 1035 | \begin{center} 1036 | {\Huge 1037 | How do you prevent existential type variables from ``leaking'' into 1038 | a global type?} 1039 | \end{center} 1040 | \end{frame} 1041 | 1042 | \begin{frame}[fragile] 1043 | \frametitle{One Last Problem} 1044 | Before a type can be promoted to the global scope: 1045 | \begin{itemize} 1046 | \item If an existential type variable has been assigned another type, 1047 | replace the existential type variable with the assigned type. 1048 | \item If an existential type variable has not been assigned another type, 1049 | generate a new, unique universal type variable and assign it to the 1050 | existential type. 1051 | \end{itemize} 1052 | 1053 | Repeat the above until the type no longer has any existential type variables 1054 | in it. 1055 | \end{frame} 1056 | 1057 | \begin{frame} 1058 | \frametitle{Type Variables: Universal} 1059 | \Large{ 1060 | \begin{definition} 1061 | The act of replacing an unassigned existential type variable with a new, 1062 | unique universal type variable is called \alert{Skolemization} (named after 1063 | Thoralf Skolem). 1064 | \end{definition} 1065 | } 1066 | \end{frame} 1067 | 1068 | \begin{frame}[fragile] 1069 | \frametitle{Summary} 1070 | \Large{ 1071 | We now have function: 1072 | 1073 | {\tt 1074 | \begin{verbatim} 1075 | typeInfer :: [ (Var, Type Var) ] 1076 | -> Expr Var 1077 | -> Matching (Type Var) 1078 | \end{verbatim} 1079 | } 1080 | 1081 | Which can be used for both type inference and type checking. 1082 | 1083 | \vspace{10pt} 1084 | 1085 | Comming soon: working code in my github repo. 1086 | } 1087 | \end{frame} 1088 | 1089 | \begin{frame} 1090 | \frametitle{Summary} 1091 | In addition, formula like the following aren't so scary any more: 1092 | 1093 | {\Huge 1094 | $$\frac{\Gamma,x:t_1\dashv{}e:t_2}{\Gamma\dashv{}\lambda{}x.e:t_1\rightarrow{}t_2}$$ 1095 | } 1096 | \end{frame} 1097 | 1098 | \begin{frame} 1099 | \frametitle{Summary} 1100 | \begin{center} 1101 | Where to go from here: 1102 | 1103 | \vspace{20pt} 1104 | 1105 | ``Types and Programming Languages'' 1106 | Benjamin C. Pierce 1107 | 1108 | \vspace{20pt} 1109 | 1110 | Then start reading papers. 1111 | \end{center} 1112 | \end{frame} 1113 | 1114 | \begin{frame} 1115 | \begin{center} 1116 | \Huge{ 1117 | fini 1118 | } 1119 | \end{center} 1120 | \end{frame} 1121 | 1122 | \end{document} 1123 | 1124 | -------------------------------------------------------------------------------- /ultimateoo.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/ultimateoo.odp -------------------------------------------------------------------------------- /webserve.odp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bhurt/presentations/8be5a65e5bba7f204294b013e9604c53a5e4f8c5/webserve.odp --------------------------------------------------------------------------------