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

runWriterのレコード フィールド アクセサであるためですWriter。実際にはほぼ同等です

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 }

その後fstsnd通常どおりに動作します。

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

newtypeあなたの例のように、値フィールドが1つだけのタイプで機能します。複数のフィールドを持つタイプの場合dataは必要です。)

于 2013-12-28T01:19:28.437 に答える