Domanda

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?

È stato utile?

Soluzione

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.

Altri suggerimenti

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top