Created
August 19, 2015 18:29
-
-
Save gabebw/a794bacec6760c00daaa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{- | |
The expression problem: Adding new data types and new functionality to | |
existing data types is at odds. | |
OOP: | |
* adding new data types is easy | |
- just write new code, and adhere to the API | |
* But adding new functionality to existing data types is hard | |
- e.g. having to add `prettyPrint` to every class in the system | |
- requires editing all existing classes | |
FP: | |
* adding new data types to the system is hard | |
- all functions that act on those data types must change to accommodate the new type | |
* but adding new functionality to existing types is easy | |
- just add a new function and pattern-match on existing data types | |
-} | |
-- Typeclasses solve the expression problem (ish): | |
-- Without changing existing code, we can make functions act on new datatypes | |
-- that conform to a typeclass. | |
-- Let's take this function: | |
-- myShow :: (Show a) => a -> String | |
-- myShow thing = "It's me: " ++ thing | |
-- Say we have this datatype: | |
data Fish = Carp | Salmon | |
-- And we want a function, `wow`, that takes these data types and says e.g. | |
-- "Wow, it's Carp", "Wow, it's Salmon", etc. | |
-- | |
-- So we write this: | |
wow Carp = "Wow, it's Carp" | |
wow Salmon = "Wow, it's Salmon" | |
-- Now let's add another data type: | |
data Metal = Steel | Gold | |
-- Since we have a new type, we need to change `wow` -- which is *code we | |
-- already wrote* -- in order to make `wow` work with our | |
-- new data type: | |
wow Gold = "Wow, it's Gold" | |
wow Steel = "Wow, it's Steel" | |
-- On the flip side, Haskell makes adding a new function that acts on all | |
-- existing data types easy. We don't have to change any existing code, this is | |
-- 100% brand new: | |
notImpressed Carp = "Ugh, it's Carp" | |
notImpressed Salmon = "Ugh, it's Salmon" | |
notImpressed Gold = "Ugh, it's Gold" | |
notImpressed Steel = "Ugh, it's Steel" | |
-- But what about typeclasses? Type classes let us add new functionality | |
-- to existing types without changing existing code. | |
-- For example, let's assume we have just `Fish`, like before. | |
class Wow a where | |
wow :: a -> String | |
data Fish = Carp | Salmon | |
instance Wow Fish where | |
wow Carp = "Wow, it's Carp" | |
wow Salmon = "Wow, it's Salmon" | |
-- Now we add Metal: | |
data Metal = Steel | Gold | |
-- We can add `wow` for Metal *without changing existing code* | |
instance Wow Metal where | |
wow Steel = "Wow, it's Steel" | |
wow Gold = "Wow, it's Gold" | |
-- Neat! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment