1

次のようなソート機能のロガーを作成しています。

bubble :: (Ord a) => [a] -> Writer [String] [a]
bubble (x:y:ys)  
        | x > y = do
                tell [show x ++ " why does this not work"]
                y:bubble(x:ys)
        | otherwise = do
                tell [show y ++ " is a number"] 
                x:bubble(y:ys)
bubble [x] = do 
            tell ["nothing works"]
            return [x] 

しかし、私はこのエラーが発生します:

 Couldn't match expected type `WriterT
                                    [String] Data.Functor.Identity.Identity [a]'
                with actual type `[a0]'
    In a stmt of a 'do' block: y : bubble (x : ys)
    In the expression:
      do { tell [show x ++ " why does this not work"];
           y : bubble (x : ys) }
    In an equation for `bubble':
        bubble (x : y : ys)
          | x > y
          = do { tell [show x ++ " why does this not work"];
                 y : bubble (x : ys) }
          | otherwise
          = do { tell [show y ++ " is a number"];
                 x : bubble (y : ys) }
Failed, modules loaded: none.

このエラー メッセージを一語一語読みましたが、問題の原因については詳しくわかりません。次のような新しいエラーのセットについて、減速なしでコンパイルを試みました。

q.hs:21:17:
    No instance for (MonadWriter [[Char]] [])
      arising from a use of `tell'
    Possible fix:
      add an instance declaration for (MonadWriter [[Char]] [])
    In a stmt of a 'do' block:
      tell [show x ++ " why does this not work"]
    In the expression:
      do { tell [show x ++ " why does this not work"];
           y : bubble (x : ys) }
    In an equation for `bubble':
        bubble (x : y : ys)
          | x > y
          = do { tell [show x ++ " why does this not work"];
                 y : bubble (x : ys) }
          | otherwise
          = do { tell [show y ++ " is a number"];
                 x : bubble (y : ys) }
Failed, modules loaded: none.
4

2 に答える 2

3

Writer w aこのような場合、が の型シノニムであることはやや残念ですWriterT w Identity a。これにより、コンパイラのエラー メッセージ (通常は非常に有益なメッセージ) の解釈が非常に難しくなります。したがって、ここでの私の提案は、エラー メッセージの内容を完全に無視して、型チェッカーのふりをすることです。

@ dave4420 は非常に良いヒントを提供してくれたと思います。それに加えて、 - の型宣言を削除しないでください。bubble代わりに、逆の方法を使用します。bubble小さなヘルパー関数に分割し、それぞれに型宣言を提供します。そうすれば、問題がどこにあるのかがより明確になるはずです。

他の唯一のヒントは、これがモナド コードを記述する際の一般的な問題であるということです。どの値がモナド型で、どの値がそうでないか、いつ「リフト」するかを覚えておくことです。

于 2012-06-27T00:11:25.727 に答える
3

正しい方向へのうなずき:

  1. の型はy何ですか?
  2. の型はbubble(x:ys)何ですか?
  3. の型は(:)何ですか?

答え:

(これらの回答でaは、 は と同じaですbubble :: (Ord a) => [a] -> Writer [String] [a]。)

  1. y :: a
  2. bubble(x:ys) :: Writer [String] [a]
    • bubbleは関数でbubble(x:ys)あり、に適用bubbleした結果ですx:ys
  3. (:) :: b -> [b] -> [b]
    • :演算子です。最初のオペランドが持つ型が何であれ、2 番目のオペランドは「最初のオペランドが持つ型のリスト」型でなければならず、結果は同じリスト型になります。

のオペランドとしてyandを指定したことを考えると、問題が何であるかがわかりますか?bubble(x:ys):

于 2012-06-26T23:55:09.100 に答える