2013-07-11 117 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是必要的。)