これは SO に関する私の最初の投稿であり、Haskell には比較的慣れていないため、間違いや私のコードが慣用的でない場合はご容赦ください。
a、f(a)、f(f(a))... の次の 2 つの直感的な説明を考えてみましょう。
A. 以下を含むリスト: a、a への f の適用、それへの fの適用、それへの f の適用...
B. i 番目の位置に i ネストされた f から a への適用を含むリスト。
私の問題はiterate
、Haskell の関数を使用してAを実行しようとして火傷を負ったことです。私の実際のアプリケーションはシミュレーションですが、次の不自然な例が問題を浮き彫りにしています。
import Control.Monad.State
example :: State Int [[String]]
step :: [String] -> State Int [String]
step l = do
currentState <- get
let result = if (currentState == 1)
then "foo":l
else "bar":l
put (currentState + 1)
return result
example = do
sequence $ take 3 . iterate (>>= step) $ return []
これらの定義により、
evalState example 1
結果:
[[],["foo"],["bar","bar"]]
明らかに、Aではなくiterate
Bです! 関数は入力リストに何かを追加するだけなので、状態に関係なく、結果が になる可能性はありません!step
step ["foo"]
["bar", "bar"]
私はここで何が起こっているのかを理解していると言わせてください.step
f(a))、状態が変更されたため、2 番目のリスト項目から取得されるのではなく、再計算されます。また、実際のアプリケーションでは、累積リストをステート内に配置することでこれを回避できることにも気付きました。
それにもかかわらず、これを投稿する理由は 2 つあります。
まず、ポイントは、実際にはBiterate
を実行するときに、初心者がAを実行すると誤解する可能性がある方法で頻繁に説明されることです。これには、Learn You A Haskell (それ以外の場合は非常に便利だと思います) が含まれますが、SO への投稿 (たとえば、hereおよびhere ) も含まれます。実際、LYAHFGG の口頭での説明は、ほぼ正確に上記の定義Aです。したがって、これが原因でバグが発生し、説明を探している他の Haskell 初心者のためのリソースとして、これに関する投稿を行うと役立つ場合があります (したがって、より正確で、技術的で、より適切な言い回しの説明を、Aとの違いiterate
以下B)。
第二に、実際にA !を実行する関数があるかどうかに興味があります。つまり、上記のステートフルな例で、[a, b = f(a), f(b), ...] というリストを作成するにはどうすればよいでしょうか? 言い換えれば、与えられた
example2 = do
firstResult <- step []
secondResult <- step firstResult
return $ [[], firstResult, secondResult]
そのために
evalState example2 1
望ましい結果が得られます
[[],["foo"],["bar","foo"]]
example2
を使用してどのように書き換えることができiterate
ますか?
初心者 Haskell リストに、のメモ化バージョンに関する関連する質問iterate
が投稿されました。ただし、そのクエリには回答がなかったようです。
怠惰が私のアプリケーションの問題であるかどうかは完全にはわかりません。の厳密なバージョンはiterate
私が望むことをしますか? 以下のような私自身の素朴な「厳密な反復」は、何の違いもないようです。
iterate' f x = x : rest
where previous = f x
rest = previous `seq` iterate f previous
このすべてに関する洞察をいただければ幸いです。