0

私は非常に簡単な問題を解決してきました. からまでLの自然数で構成された の長さのすべての減少するシーケンスの生成は、辞書式の順序です. しかし、私は非常に奇妙な問題に遭遇しました。見てみましょう:1M

c :: (Ord a, Num a, Enum a) => a -> a -> [[a]]
c m 1 = map return [1..m]
c m l = do
          n   <- [l..m]
          res <- c (n - 1) (l - 1)
          return $ n:res

c' :: (Ord a, Num a, Enum a) => a -> a -> [[a]]
c' m = helper 1 m where
 helper :: (Ord a, Num a, Enum a) => a -> a -> a -> [[a]]
 helper a b 1 = map return [a..b]
 helper a b l = do
                  n    <- [a..b]
                  True <- return $ (l - 1 <= n)
                  res  <- helper a (n - 1) (l - 1)
                  return (n:res)

したがって、明らかに、これらの 2 つの関数はまったく同じことを行います (いくつかのテストで確認しましたが、両方とも正しい結果が得られますc 100 98) c' 100 98。かかります:

c 100 98: 約 5 秒;

c' 100 98: 約 70 秒;

私が述べたように、結果は同じです。

[a..b]なので、毎回生成するのはちょっと不安なのですが、ちょっと聞いてみたら、Haskell はすぐにパターンマッチするのではなく、遅延評価で遅延するのではないかという提案がありました。の大量の余分な呼び出しが発生しc'ます。しかし、2 番目の理論は完全には成り立ちませんでした。GHCi コマンド プロンプトから直接コードにブレークポイントを設定し、 の値を監視しnたところ、遅延パターン マッチングが当てはまらないことがわかりました。

問題は実際にはenumFromTo機能にあるのでしょうか、それとも他の理由がありますか?

4

2 に答える 2