Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell newtype syntax

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?

like image 336
Rumca Avatar asked Jul 11 '13 17:07

Rumca


2 Answers

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

  1. More convient syntax since this sort of accessor code is quite common
  2. The ability for functional updates
  3. A few other extensions

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.

like image 195
Daniel Gratzer Avatar answered Oct 16 '22 06:10

Daniel Gratzer


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.)

like image 35
misterbee Avatar answered Oct 16 '22 07:10

misterbee