Please help me to understand the following definition:
newtype Writer w a = Writer { runWriter :: (a,w) }
instance (Monoid w) => Monad (Writer w) where
return a = Writer (a,mempty)
(Writer (a,w)) >>= f = let (a',w') = runWriter $ f a in Writer (a',w `mappend` w')
Why is runWriter is declared as
runWriter :: (a,w)
when its actual type is:
runWriter :: Writer w a -> (a, w)
Once I tried with ghci I realized this must be some implicit argument since type "a" has to be determined, but what is exactly happening here?
Because runWriter
is a record field accessor on Writer
. It's actually almost equivalent to
runWriter (Writer x) = x
Haskell just has records to give
eg
someWriter{runWriter = (new, values)} -- Returns a new Writer.
If it helps, think of it as something like a "functional getter" in the roughest sense. This might not seem terribly important with 1 field, you can always pattern match, but when you have 5 fields, records + functional updates are super helpful. See LYAH for a more in depth explanation.
Another way to look at it: You can imagine defining 2-tuples like so (if the special (,)
syntax weren't already a special built-in)
data (,) a b = (,) { fst :: a, snd :: b }
and then fst
and snd
would behave as normal:
fst :: (a,b) -> a
fst (x,y) = x
(newtype
as in your example works for types with only one value field. for types with multiple fields, data
is needed.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With