We're reading Learn You a Haskell for Great Good! at the office's non-fiction book club! This covers the second two parts of chapter 11 (Functors, Applicative Functors and Monoids) — from the section entitled 'The newtype keyword' and onwards.
Legend
- Regular text summarizes a point the document made.
- Italicized font expresses my terrible, terrible opinions or attempts at explanation.
- Highlighted text indicates that this note was important to my understanding, and if it's italicized, then I even thought of it myself!
Notes
- The newtype keyword
- Recap
- Data = ADT
- Type = type synonym
- <*> can logically have different implementations for e.g. a list
- Such as ZipList vs []
- Adding additional typeclass instances for a type
- Can be done by wrapping the existing type in a `data` with a single constructor.
- Use a record to make it easier to extract contents.
- Downside: slight perf overhead.
- Use newtype: wraps an existing type w/o overhead.
- Vs. data: can't define a union of types.
- Newtypes can use `deriving`
- Note: newtypes totally resolve my issue re. the absence of a Haskell equivalent to e.g. Kotlin's inline classes, or Scala's value classes.
- It's also useful for the specific case of implementing type classes over pairs.
- newtype laziness
- Evaluating `undefined` causes an exception and stops execution (?)
- Pattern matching over a data with one constructor requires destructuring, whereas doing so over a newtype doesn't.
- I had to
follow up elsewhere to understand this better. A Stack Overflow response explained it well:
Both newtype and the single-constructor data introduce a single value constructor, but the value constructor introduced by newtype is strict and the value constructor introduced by data is lazy. So if you have
data D = D Int
newtype N = N Int
Then N undefined is equivalent to undefined and causes an error when evaluated. But D undefined is not equivalent to undefined, and it can be evaluated as long as you don't try to peek inside.
From <https://stackoverflow.com/questions/2649305/why-is-there-data-and-newtype-in-haskell>
- type vs newtype vs data
- type: the two types are identical. Imagine that the synonym is replaced by the original value.
- newtype: "wraps" values to assist w/implementing type classes sometimes. One constructor + field.
- data: union types, multiple constructors + fields.
- Monoids
- Recap
- Typeclasses encode a group of similar operations that over a variety of types.
- Multiplication by 1 and concatenation to the empty list have similar operations (typeclass of monoid):
- Functions take two parameters
- Input and output have same type
- It has at least one constant value which makes the operation do nothing.
- Associative (can move parentheses around), but can't rearrange in "equation"
- Looking at the type class:
class Monoid m where
mempty :: m
mappend :: m -> m -> m
mconcat :: [m] -> m
mconcat = foldr mappend mempty
- m is concrete; it doesn't take any type parameters
- Note: mappend is unfortunately named; doesn't append anything in many implementations.
- Normally don't need to implement mconcat; default is fine (unless done for perf)
- Laws:
- (see text; self-explanatory)
- An examination of the instance Monoid List a.
- (it works as expected)
- newtype's + instances of Monoid for Product, Sum, "Any" (boolean), and "All" (boolean) also exist.
- || and false is the left value, && and true is the left value (mempty)
- The text has promised that this will become useful at some point … it's kind of hard to see where that is, so far? I'd imagine this is where Real World Haskell (or a contemporary) would highlight some applications instead of making a promise/joke.
- Ordering (the data) has a Monoid instance, too.
- In an extraordinarily contrived example, if you have a sequence of `Ordering` and wish to flatten them to a single `Ordering` and it makes sense that you only care about the first non-EQ result left-to-right, `mconcat` on the Monoid over Ordering makes sense.
- General note on what appears to be a common Haskell pattern: have specialized tools (typeclasses, functions, etc.) available s.t. solutions can be composed out of those. Kind of similar to having an STL which comes with a large number of helper functions.
- Maybe is a monoid with several implementations:
- Propagate `mappend` to children, if it's a Maybe of a monoid.
- `First`: left to right, `mappend` finds the first 'Just' value
- Foldable
- `Foldable` defines implementations of `foldr` for the Foldable typeclass, not specifically lists (but it also works on lists).
- It works on `Maybe` (Java was lacking this until v11 …)
- Instance of Foldable for a custom Tree type
- Map over node value, `mappend` with foldMap over left and right branches.
- Recall: foldMap reduces to any Monoid, so it can be useful in other circumstances (e.g. flatten a tree (list monoid), or search for the presence of a value (boolean monoid))
Merkur 37C Safety Razor Review – Merkur 37C
ReplyDeleteThe Merkur https://deccasino.com/review/merit-casino/ 37c deccasino is an excellent short handled DE safety razor. It is more worrione.com suitable communitykhabar for both heavy and non-slip hands and is therefore a great option for experienced