2013-07-11 203 views
8

請幫助我理解了如下定義:哈斯克爾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試過我意識到這肯定是一些隱含的論點,因爲類型「a」必須確定,但是到底發生了什麼?

回答

8

因爲runWriterWriter上的記錄字段存取器。它實際上幾乎等同於

runWriter (Writer x) = x 

哈斯克爾剛剛已經記錄給

  1. 更多無限便捷語法,因爲這種訪問代碼是很常見
  2. 進行功能更新的能力
  3. 其他幾個延伸

例如

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

如果有幫助,可以把它看作最粗糙的「功能吸氣劑」。這對於1字段可能看起來不是非常重要,你總是可以匹配模式,但是當你有5個字段時,記錄+功能更新是超級有用的。有關更深入的解釋,請參閱LYAH

0

另一種方式來看待它:你可以想像定義,像這樣2元組(如果特殊(,)語法不是已經是一個特殊的內置)

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

然後fstsnd將表現正常:

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

newtype在你的榜樣工程類型只有一個值字段類型的多個字段,data是必要的。)