9

请帮助我理解以下定义:

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”,但这里到底发生了什么?

4

2 回答 2

9

因为runWriterWriter. 它实际上几乎等同于

runWriter (Writer x) = x

Haskell 有记录可以提供

  1. 更方便的语法,因为这种访问器代码很常见
  2. 功能更新的能力
  3. 其他一些扩展

例如

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

如果它有帮助,请将其视为最粗略意义上的“功能性吸气剂”。这对于 1 个字段可能看起来不是很重要,您始终可以进行模式匹配,但是当您有 5 个字段时,记录 + 功能更新非常有用。有关更深入的解释,请参阅LYAH 。

于 2013-07-11T18:02:57.403 回答
1

另一种看待它的方式:您可以想象像这样定义 2 元组(如果特殊(,)语法还不是特殊的内置)

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

然后fstandsnd将表现正常:

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

newtype在您的示例中适用于只有一个值字段的类型。对于具有多个字段的类型,data需要。)

于 2013-12-28T01:19:28.437 回答