Haskell の基本の 1 つに問題があります: Fold + 無名関数
でbin2decプログラムを開発していfoldl
ます。
解決策は次のようになります。
bin2dec :: String -> Int
bin2dec = foldl (\x y -> if y=='1' then x*2 + 1 else x*2) 0
foldl
/の基本的な考え方はfoldr
理解できますが、パラメータの意味がわかりませんx y
。
Haskell の基本の 1 つに問題があります: Fold + 無名関数
でbin2decプログラムを開発していfoldl
ます。
解決策は次のようになります。
bin2dec :: String -> Int
bin2dec = foldl (\x y -> if y=='1' then x*2 + 1 else x*2) 0
foldl
/の基本的な考え方はfoldr
理解できますが、パラメータの意味がわかりませんx y
。
の種類を見るfoldl
foldl :: (a -> b -> a) -> a -> [b] -> a
検討foldl f z list
そのため、foldl は基本的にリスト (または折りたたみ可能なもの) に対して段階的に機能し、左から 1 つの要素を取得して適用f z element
し、残りの要素を折りたたみながら、次のステップで使用する新しい要素を取得します。基本的に、foldl の簡単な定義が理解の助けになるかもしれません。
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
Haskell wikiの図は、より良い直感を構築するのに役立つかもしれません。
あなたの関数f = (\x y -> if y=='1' then x*2 + 1 else x*2)
を考えて、 のトレースを書いてみてくださいfoldl f 0 "11"
。ここ"11"
は同じです['1','1']
foldl f 0 ['1','1']
= foldl f (f 0 '1') ['1']
ここで、f は 2 つの引数 (最初は整数、2 番目は文字) を取り、整数を返す関数です。だから この場合x=0
そしてy='1'
, そうf x y = 0*2 + 1 = 1
= foldl f 1 ['1']
= foldl f (f 1 '1') []
もう一度適用しf 1 '1'
ます。などx=1
など。y='1'
_f x y = 1*2 + 1 = 3
= foldl f 3 []
foldl
空のリストの最初の定義を使用します。
= 3
これは「11」の 10 進数表現です。
タイプを使おう!:t
GHCi に続けて任意の関数または値を入力すると、そのタイプを確認できます。に型を尋ねると、次のようになります。foldl
Prelude> :t foldl
foldl :: (a -> b -> a) -> a -> [b] -> a
入力リストはタイプ[b]
なので、b
s のリストです。出力タイプはa
、これから作成するものです。また、タイプのフォールドの初期値も指定する必要がありますa
。関数は型です
a -> b -> a
最初のパラメーター ( a
) は、これまでに計算されたフォールドの値です。2 番目のパラメーター ( b
) は、リストの次の要素です。だからあなたの例では
\x y -> if y == '1' then x * 2 + 1 else x * 2
パラメータx
は、これまでに計算した 2 進数y
で、リスト内の次の文字 ( a'1'
または a '0'
) です。