Skip to main content

Notes on Learn you a Haskell (Newtype and Monoids)

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:
    1. Propagate `mappend` to children, if it's a Maybe of a monoid.
    2. `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))

Comments

  1. Merkur 37C Safety Razor Review – Merkur 37C
    The 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

    ReplyDelete

Post a Comment

Popular posts from this blog

Notes on Learn you a Haskell (Functors and Applicative Functors)

We're reading Learn You a Haskell for Great Good! at the office's non-fiction book club! This covers the first two parts o f chapter 11 (Functors, Applicative Functors and Monoids) up to the end of the discussion on applicative functors. Legend Regular text summarizes a point the document made. Italicize d font expresses my terrible, terrible opinions or attempts at explaination. Highlighted   text indicates that this note was important to my understanding, and if it's italicized, then I even thought of it myself! Notes Haskell's type system doesn't require placing types in a hierarchy, which can be useful for designs. Typeclasses are "open" for extension Recap: `Eq` (equateable) and `Functor` (mappable) Functors Recap e.g. lists, Maybe, trees. Typeclass fmap :: (a->b) -> f a -> f b Functors are "computational context" e.g. that a value exists or not, that there are multipl...