2013-07-11 4 views
8

Пожалуйста, помогите мне понять следующее определение:Haskell синтаксис Newtype

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

Почему runWriter объявлен как

runWriter :: (a,w) 

, когда его фактический тип:

runWriter :: Writer w a -> (a, w) 

После ввода попробовал с ghci. Я понял, что это должен быть какой-то неявный аргумент, так как нужно определить тип «а», но что здесь происходит?

ответ

8

Потому что runWriter является вспомогательным устройством для записей на Writer. Это на самом деле почти эквивалентно

runWriter (Writer x) = x 

Haskell просто имеют записи, чтобы дать

  1. Более Convient синтаксиса, так как этот вид аксессора кода является довольно распространенным
  2. Способности функциональных обновлений
  3. Несколько других расширения

например

someWriter{runWriter = (new, values)} -- Returns a new Writer. 

Если это помогает, подумайте об этом как о «функциональном геттере» в грубом смысле. Это может показаться не очень важным с 1 полем, вы всегда можете сопоставить образец, но когда у вас есть 5 полей, записи + функциональные обновления очень полезны. См. LYAH для более подробного объяснения.

0

Другим способом смотреть на это: Вы можете себе представить определение 2-кортежей как так (если специальный (,) синтаксис не были уже специальным встроенным)

data (,) a b = (,) { fst :: a, snd :: b } 

, а затем fst и snd будет вести себя как обычно:

fst :: (a,b) -> a 
fst (x,y) = x 

(. newtype, как в вашем примере работает для типов только одно поле значения для типов с несколькими полями, data требуется.)

Смежные вопросы