├── 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 | - 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.
14 |
15 | - 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!
18 |
19 | - 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 |
24 |
25 | - The "four faces" of monads:
- Where they come from (category
26 | theory)
- How they are implemented
- How they are
27 | used
- 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.
30 |
31 | - 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 | 1 | Left Identity: | (return x) >>=
654 | f | <=> | f x |
655 |
656 | 2 | Right Identity: | m >>=
657 | return | <=> | m |
658 |
659 | 3 | Associativity: | (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 |
- An action
698 | - Returning a value
699 | - In a domain that has special abilities
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 | Monad | Special abilities |
708 | IO | Can do I/O and/or side-effects |
709 | State | Has read/write access to a "global variable" |
710 | Reader | Has read-only access to a "global variable" |
711 | Writer | Has write-only access to a "global variable" |
712 | Maybe | May not produce an output |
713 | List | May produce multiple outputs |
714 |
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
--------------------------------------------------------------------------------