10. What are Laws?
Laws are statements made about
equivalence of expressions.
Some Laws come from Maths
Abstract Algebra
11. What are Laws?
Integer addition obeys the
Associativity Law
Wherever we use Integer
Addition, we can use the
properties of the law to our
advantage.
7 + 3 + 5 + 2 = 7 + (3 + 5) +
2
For an implementor, the Law is a
Contract!
13. What are Laws?
Laws are not checked by the type
system
Laws can be broken by
implementations
Verification is usually done by
hand
Alternatively, QuickCheck.
14. What are Laws?
Statements of Equivalence
Contracts for the Implementor
Laws are not checked by the type
system
Origins in Maths. (Programming)
15. What are Laws Common Laws
Legal Benefits Breaking Laws
29. Functor Laws
fmap id x = id x
fmap (g . h) =
(fmap g) . (fmap h)
where
id a = a
id a = a
30. Not a Functor
instance Functor [] where
fmap f [] = []
fmap f (x:xs) = (f x):(f x):(fmap f xs)
31. Functor Laws
Functor is a structure with an
`fmap` that does not affect that
structure, just the values
inside.
To modify the structure you need
a different typeclass. The laws
prevent it.
32. What are Laws Common Laws
Legal Benefits Breaking Laws
33. Legal Benefits
Meaning to Multi-function
Typeclasses
Greater understanding of
Typeclasses
Substitution of Expressions
44. Consequences of
Illegal Behaviour
Specific code using a
Bijection[Int, String] might be
fine.
What if I write a function that
uses a Bijection[A,B]?
45. What are Laws Understanding Laws
Legal Benefits Breaking Laws
46. Laws are Good
Laws have a huge impact on the way
we code (already).
Refactoring, Algebraic Laws
Taking advantage of laws is a
powerful programming technique.
Understanding typeclasses,
writing new instances
Watch out for Law breakers!
Alternative title: Law & Order: Refactoring Crime Unit.
We need to remember to come back to laws.
Understanding Laws: Explain a few fundamental laws, then learn some typeclasses by focussing on their laws.
Familiarity from School Example of the use of a law. What’s it name? Note some similarities to programming: * Expressions on the left hand side and right hand side * Substitutability
Generalised to Addition Made the integers parameters Only ‘+’ is left as an operator
Generalised statement about any binary operation Binary - takes 2 arguments, eg. plus, times, etc.
We’ve now seen an example of a law, and where it came from We’ve seen an example of a function satisfying a law
We can leverage the law in programming: doing the operations in order that is most clear to readers, or fastest. If you’re writing a function, and you’re calling it integer addition, you need to satisfy the law. Or you will be taken down. The law is just like programming with contracts.
Explain the signature: function name, syntax/puncutation, arguments, return type. Where does the law fit into this? It doesn’t.
Technique for hand verification is equational reasoning, see that later Occasionally verified with QuickCheck, but it’s hard to satisfy yourself. QuickCheck requires a good Arbitrary. Easy to get wrong.
Statements of equivalence? Refactoring! Substituting methods for expressions, expressions for expressions, etc. Contracts in programming (not null parameters, etc.) are very useful. When a new law is required, the decision is made by the community. The most useful law is generally obvious.
Tackle in 2 parts. First we’ll look at some laws that may be familiar. The ones from abstract algebra, that apply to things like addition and multiplication. Second part we’ll look at some typeclasses, and the laws they require. Generalising part 1.
Someone tell me a way of remembering this
Step from list to the operation Sum the list in any pairing of subsequent parts
Flipping. String addition, not satisfied. Prefix becomes suffix. + in java: commutative for integers, not commutative for strings. Should + be overloaded like this?
Start with our application of the associative law. Commutative law says we can swap all the parts Now, if we parallelise this operation as summing into an accumulator, it now longer matters which parts of our computation come out first. Because Laws! How useful!
This is interesting, because there are now 2 parts. The identity value, and a binary operation. There’s a relationship here between two things. TODO: show a + 0, a * 1, matrix * I
Now to typeclasses, which is where things get real. Now I want to build on what we’ve just seen. Particularly, Associativity (changing the parentheses), and Identity.
Explain the code. This is an interface. Note there’s something missing. We have 2 functions we need to implement, but nothing about how they should be implemented yet. Also, there’s nothing that ties these 2 functions together. At this point we know where this is going. Anyone want to take a stab?
This is interesting, because there are now 2 parts. The identity value, and a binary operation. There’s a relationship here between two things. Relationship is what is important. Jump back.
Laws tie these functions together. Each could be implemented independently.
This is interesting, because there are now 2 parts. The identity value, and a binary operation. There’s a relationship here between two things. Relationship is what is important. Jump back.
A step up from what we’re doing. Functor.
Explain the code again. What is a functor? something you can map over. Anything with a map function. Transforming contents of a containing is one of the most obvious implementations.
Explain each law on its own. Space is function application. Show that they are statements of equivalence. Meaning: * does not change the structure * changes a value without changing its context
Duplicates the first functor value. If we do fmap with identity, we’ll end up with an extra value out the front. This is not the same as just doing identity. We’ll see how to implement a real one soon
Laws tell us what a functor really is.
understanding Monoid: Identity means nothing without an Mappend. Defined in terms of mappend. understanding fmap: preserving the structure. We can use that to help us define instances. Substitution: Tooling can take advantage of this.
This is not a law. This is a rewrite statement in GHC. Specific to lists, however it could be (because of laws) changed to fmap. Then it looks very similar to the statement of the fmap for composition.
Verification is sometimes hard.
Splitting apart Monoid and Monad. What can we say about these functions? What laws can we write? Nothing. They both require other functions to define themselves *meaningfully*.
Verification is sometimes hard.
A bijection: Everything in X maps to EXACTLY one item in Y. Every X is covered. Every Y is covered. There must be an inverse.
Every Int must map to a unique String, *every* string must map to a unique integer. Otherwise this is not a bijection. Trivial to prove its not the case.
Every Int must map to a unique String, *every* string must map to a unique integer. Otherwise this is not a bijection. Trivial to prove its not the case.
Parallelism, optimisations
Lens is amazing. Look for his talk at NY Haskell. Pipes is a laws-driven implementation of iteratees.