haskell-jp / beginners #22 at 2022-10-14 17:48:28 +0900

Haskellでのデバッグ方法がわからず、質問させていただいてもよろしいでしょうか。
やりたいことは、JavaScriptの`console.log`のように、関数のなかの変数を`GHCi`のコンソールに出力したいです。
具体的には、以下の関数で、`repeatedL1` の部分がどんな値になっているかを見たいです。
cartCombine :: (a -> b -> c) -> [a] -> [b] -> [c]
cartCombine func l1 l2 = zipWith func newL1 cycledL2
    where
        nToAdd = length l2
        repeatedL1 = map (take nToAdd . repeat) l1
        newL1 = mconcat repeatedL1
        cycledL2 = cycle l2

ここで、
repeatedL1 = map (take nToAdd . repeat) l1
show repeatedL1
newL1 = mconcat repeatedL1
……

などとすると、エラーになってしまいます。

ご教示いただけますと幸いです。
よろしくお願いいたします。
デバッグ用途では Debug.Trace.trace が用意されてます!
https://hackage.haskell.org/package/base-4.17.0.0/docs/Debug-Trace.html#v:trace
使い方はこんな感じ
https://wandbox.org/permlink/Mj4mJuClHrgnI8Mk
今回のように変数の中身を見る場合、同じ Debug.Trace モジュールに入っている traceShowId 関数を使うのが特におすすめです。
@kakkun61 @igrep

ありがとうございます!

立て続けに申し訳ありません。
以下のような形で、`traceShowId` を書いたのですが、
「変数が、showのインスタンスではない」というエラーになってしまいました。
この場合、どうすれば`repeatedL1` の中身を見ることができるでしょうか。

書いたコード
cartCombine :: (a -> b -> c) -> [a] -> [b] -> [c]
cartCombine func l1 l2 = zipWith func newL1 cycledL2
    where
        nToAdd = traceShowId (length l2)
        repeatedL1 = traceShowId (map (take nToAdd . repeat) l1)
        newL1 = mconcat repeatedL1
        cycledL2 = cycle l2

エラーメッセージ
error:
    • No instance for (Show a) arising from a use of 'traceShowId'
      Possible fix:
        add (Show a) to the context of
          the type signature for:
            cartCombine :: forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
手っ取り早いのは cartCombine の型を
cartCombine :: Show a => (a -> b -> c) -> [a] -> [b] -> [c]

にすることですね
Show のインスタンスでない型を a にすることができなくなりますが
実は*珍しく*GHCの
Possible fix:
  add (Show a) to the context of

で始まるヒントが役に立っています(個人的な経験上このヒントはあまり役に立たないのですが...)
指示どおり、 cartCombine :: (a -> b -> c) -> [a] -> [b] -> [c] における型変数 aShow 型クラスの制約を加えてください:
cartCombine :: Show a => (a -> b -> c) -> [a] -> [b] -> [c]

そして、もし bc についても No instance for (Show b) ... のようなエラーメッセージがでる場合、同様に b , cについても加えます:
-- 型クラス制約を複数列挙する場合、カッコで囲ってカンマで列挙する点に注意
cartCombine :: (Show a, Show b, Show c) => (a -> b -> c) -> [a] -> [b] -> [c]

この (Show a, Show b, Show c) =>は、デバッグのためだけに必要になってしまう制約で、 よく言われる頭の痛い問題です。
一応、サードパーティーのパッケージで解決することはできますが、ここでは Show を追加するのが簡単かと思います。
Show 型クラスの制約を加えて変数が見られました!
ありがとうございます!