<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>【foldl】タグの記事一覧｜Haskell Tech</title>
	<atom:link href="https://haskell-tech.nkhn37.net/tag/foldl/feed/" rel="self" type="application/rss+xml" />
	<link>https://haskell-tech.nkhn37.net</link>
	<description>Haskell学習サイト</description>
	<lastBuildDate>Sun, 31 Mar 2024 06:55:00 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</generator>

<image>
	<url>https://haskell-tech.nkhn37.net/wp-content/uploads/2023/12/cropped-lion-normal-clear-32x32.png</url>
	<title>【foldl】タグの記事一覧｜Haskell Tech</title>
	<link>https://haskell-tech.nkhn37.net</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>【Haskell】foldl関数、foldr関数の基本的な使い方 ~畳み込み~</title>
		<link>https://haskell-tech.nkhn37.net/haskell-foldl-foldr-basic/</link>
					<comments>https://haskell-tech.nkhn37.net/haskell-foldl-foldr-basic/#respond</comments>
		
		<dc:creator><![CDATA[naoki-hn]]></dc:creator>
		<pubDate>Sat, 30 Mar 2024 20:00:00 +0000</pubDate>
				<category><![CDATA[関数]]></category>
		<category><![CDATA[foldl]]></category>
		<category><![CDATA[foldr]]></category>
		<category><![CDATA[高階関数]]></category>
		<guid isPermaLink="false">https://haskell-tech.nkhn37.net/?p=481</guid>

					<description><![CDATA[Haskellで畳み込み計算をするためのfoldl関数とfoldr関数の使い方を解説します。 畳み込み関数 (foldl, foldr) 畳み込みとは、適用する関数、初期値、畳み込み可能な型のデータ(例えばリスト)を受け]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Haskellで畳み込み計算をするための<span class="marker"><strong><code>foldl</code>関数と<code>foldr</code>関数の使い方</strong></span>を解説します。</p>



<h2 class="wp-block-heading">畳み込み関数 (foldl, foldr)</h2>



<p class="wp-block-paragraph">畳み込みとは、適用する関数、初期値、畳み込み可能な型のデータ(例えばリスト)を受け取って単一の値にする計算のことを言います。Haskellでは、畳み込み関数の代表的なものとして<span class="marker"><strong><code>foldl</code></strong></span>関数と<span class="marker"><strong><code>foldr</code></strong></span>関数があります。</p>



<p class="wp-block-paragraph">これらの関数において、<code>l</code>は「left」、<code>r</code>は「right」を表しており、<code>foldl</code>は左畳み込み、<code>foldr</code>は右畳み込みと言います。これらは左から値を畳み込んでいくのか、右から値を畳み込んでいくのかの違いがあります。</p>



<p class="wp-block-paragraph"><code>foldl</code>関数や<code>foldr</code>関数のように引数に関数を受け取る関数は、高階関数と言います。高階関数の概要については「<a href="https://haskell-tech.nkhn37.net/haskell-higher-order-functions-basic/" target="_blank" rel="noreferrer noopener">高階関数の基本</a>」でまとめているので参考にしてください。畳み込み関数(<code>foldl</code>, <code>foldr</code>)は、高階関数の中でも代表的な関数であり、関数型プログラミングにおいて中心的な関数の一つです。他のプログラミング言語では、<code>reduce</code>という関数名の場合もあります。</p>



<p class="wp-block-paragraph">この記事では、畳み込み計算をするための<span class="marker"><strong><code>foldl</code>関数と<code>foldr</code>関数の使い方</strong></span>を解説します。</p>



<div class="wp-block-jin-gb-block-box concept-box5">
<p class="wp-block-paragraph">関数型プログラミングの中心的な関数としては他にも<code>map</code>関数や<code>filter</code>関数があります。以下のページでまとめていますので参考にしてください。</p>



<ul class="wp-block-list">
<li><a href="https://haskell-tech.nkhn37.net/haskell-map-function-basic/" target="_blank" rel="noreferrer noopener">map関数の基本的な使い方</a></li>



<li><a href="https://haskell-tech.nkhn37.net/haskell-filter-function-basic/" target="_blank" rel="noreferrer noopener">filter関数の基本的な使い方</a></li>
</ul>
</div>



<h2 class="wp-block-heading">foldl関数の基本的な使い方</h2>



<p class="wp-block-paragraph"><span class="marker"><strong><code>foldl</code></strong></span>関数は、Haskellにおいてリスト等の<code>Foldable</code>な型を畳み込むために使用します。「<code>l</code>」は「left」を表しており、<span class="marker"><strong>左畳み込み</strong></span>とも言われます。</p>



<p class="wp-block-paragraph"><code>foldl</code>関数の型シグネチャは以下のようになっています。</p>



<div class="wp-block-jin-gb-block-box-with-headline kaisetsu-box4"><div class="kaisetsu-box4-title">foldl関数</div><div class="wp-block-syntaxhighlighter-code "><pre class="brush: haskell; gutter: false; title: ; notranslate">
foldl :: Foldable t =&gt; (b -&gt; a -&gt; b) -&gt; b -&gt; t a -&gt; b
</pre></div></div>



<p class="wp-block-paragraph"><code>foldl</code>関数は、以下の3つの引数を取ります。</p>



<ol class="wp-block-list">
<li>関数 <code>(b -&gt; a -&gt; b)</code>：リストの各要素と累積値に適用され、新しい累積値を生成します。例えば、<code>(+)</code>は2つの数を受け取り、その和を返す2項関数です。</li>



<li>初期値 <code>b</code>：畳み込みを開始するための値です。例えば、数値リストを畳み込む場合の初期値として<code>0</code>がよく使用されます。</li>



<li>畳み込まれるリスト <code>t a</code>：Foldable型クラスのインスタンスであり、畳み込み対象となるデータです。例えば、<code>Int</code>のリスト(<code>[Int]</code>)等が該当します。</li>
</ol>



<p class="wp-block-paragraph">ここで、<code>Foldable</code>というのは型クラスを表しています。<code>t</code>は<code>Foldable</code>型クラスのインスタンスである必要があります。今回は簡単のため<code>Foldable</code>のインスタンスであるリストを使った例を紹介しますが、他の型でも<code>foldl</code>関数は使用できます。他の<code>Foldable</code>型クラスのインスタンスである型としては<code>Tree</code>型や<code>Maybe</code>型などが該当します。</p>



<h3 class="wp-block-heading">foldl関数の使用例</h3>



<h4 class="wp-block-heading">数値の畳み込み</h4>



<p class="wp-block-paragraph"><code>foldl</code>関数を使用して、数値のリストを畳み込む場合には以下のようにします。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: haskell; title: ; notranslate">
-- 数値の畳み込み
plusFoldl :: &#x5B;Int] -&gt; Int
plusFoldl xs = foldl (+) 0 xs
</pre></div>

<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; gutter: false; title: ; notranslate">
【実行結果例】
ghci&gt; plusFoldl &#x5B;1, 2, 3, 4, 5]
15
</pre></div>


<p class="wp-block-paragraph">上記で定義した<code>plusFoldl</code>関数は、<code>foldl</code>を使用してリスト<code>xs</code>の中の全ての数値を<span class="marker2">左から</span>順に加算<code>(+)</code>し、その合計値を返します。左から順に足しこんでいく基準の初期値は<code>0</code>となります。実行結果例をわかる通り<code>[1, 2, 3, 4, 5]</code>を引数に渡すと結果は<code>15</code>となります。</p>



<h3 class="wp-block-heading">foldl関数の動作を理解する</h3>



<p class="wp-block-paragraph">上記の例を見て<code>foldl</code>関数がどのような結果となるかは分かったかと思いますが、より関数の動作を理解するには自分で実装するとどうなるかを考えてみることが非常に役に立ちます。</p>



<p class="wp-block-paragraph"><code>foldl</code>関数は、型シグネチャを見るとわかる通りリスト限定のものではありませんが、リストを前提として左畳み込みを自分で実装してみる場合の<code>myFoldl</code>関数は以下のように実装することができます。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: haskell; title: ; notranslate">
-- foldlを自分で実装する
myFoldl :: (b -&gt; a -&gt; b) -&gt; b -&gt; &#x5B;a] -&gt; b
myFoldl f z &#x5B;] = z
myFoldl f z (x:xs) = myFoldl f (f z x) xs
</pre></div>


<p class="wp-block-paragraph">上記の関数において<code>f</code>を<code>(+)</code>、<code>z</code>を<code>0</code>、xsを<code>[1, 2, 3, 4, 5]</code>と考えてどのような動きをしているか考えてみましょう。具体的にどのように処理が流れていくかを記載してみると以下のようになります。</p>


<div class="wp-block-image">
<figure class="aligncenter size-large"><img fetchpriority="high" decoding="async" width="1024" height="682" src="https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-5-1024x682.png" alt="foldl関数の説明" class="wp-image-500" srcset="https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-5-1024x682.png 1024w, https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-5-300x200.png 300w, https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-5-768x511.png 768w, https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-5.png 1326w, https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-5-1024x682.png 856w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p class="wp-block-paragraph"><code>myFoldl</code>関数は、再帰的に定義されています。「<code>myFoldl f z (x:xs) = myFoldl f (f z x) xs</code>」の部分に注目してみると、初期値<code>0</code>とリストの先頭要素<code>1</code>に対して引数で与えられた関数<code>(+)</code>を適用し、その結果が次の初期値となっています。このように順に計算をしていくと計算結果の<code>15</code>が得られます。具体的には<code>(((((0 + 1) + 2) + 3) + 4) + 5) = 15</code>のように計算されていることが分かるかと思います。</p>



<h2 class="wp-block-heading">foldr関数の基本的な使い方</h2>



<p class="wp-block-paragraph"><span class="marker"><strong><code>foldr</code></strong></span>関数も、<code>foldl</code>関数と同様にリスト等の<code>Foldable</code>な型を畳み込むために使用します。「<code>r</code>」は「right」を表しており、<span class="marker"><strong>右畳み込み</strong></span>とも言われます。</p>



<p class="wp-block-paragraph"><code>foldr</code>関数の型シグネチャは以下のようになっています。</p>



<div class="wp-block-jin-gb-block-box-with-headline kaisetsu-box4"><div class="kaisetsu-box4-title">foldr関数</div><div class="wp-block-syntaxhighlighter-code "><pre class="brush: haskell; gutter: false; title: ; notranslate">
foldr :: Foldable t =&gt; (a -&gt; b -&gt; b) -&gt; b -&gt; t a -&gt; b
</pre></div></div>



<p class="wp-block-paragraph"><code>foldl</code>関数と非常に似た型シグネチャであることが分かるかと思いますが、違いとしては第1引数で受け取る関数の型が<code>(a -> b -> b)</code>となっていて、<code>a</code>と<code>b</code>が逆転しています。これは、<code>foldr</code>関数がリストの要素を右から畳み込んでいくことを意味しています。</p>



<h3 class="wp-block-heading">foldr関数の使用例</h3>



<h4 class="wp-block-heading">数値の畳み込み</h4>



<p class="wp-block-paragraph"><code>foldl</code>関数と同じように<code>foldr</code>関数を用いて数値の畳み込みをする例を見てみましょう。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: haskell; title: ; notranslate">
-- 数値の畳み込み
plusFoldr :: &#x5B;Int] -&gt; Int
plusFoldr xs = foldr (+) 0 xs
</pre></div>

<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; gutter: false; title: ; notranslate">
【実行結果例】
ghci&gt; plusFoldr &#x5B;1, 2, 3, 4, 5]
15
</pre></div>


<p class="wp-block-paragraph">上記で定義した<code>plusFoldr</code>関数は、<code>foldr</code>を使用してリスト<code>xs</code>の中の全ての数値を<span class="marker2">右から</span>順に加算<code>(+)</code>し、その合計値を返します。右から順に足しこんでいく基準となる初期値は<code>0</code>となります。実行結果例をわかる通り、<code>[1, 2, 3, 4, 5]</code>を引数に渡すと結果は15となります。</p>



<h3 class="wp-block-heading">foldr関数の動作を理解する</h3>



<p class="wp-block-paragraph">数値を畳み込む例を見てきましたが結果としては<code>foldl</code>関数と<code>foldr</code>関数では同じ結果になりました。しかし、内部的には全く異なる動作をしています。</p>



<p class="wp-block-paragraph"><code>foldl</code>関数でも見てきたように<code>foldr</code>関数についても、自分で実装してみることにしてみましょう。<code>foldr</code>関数をリストに対して実装した<code>myFoldr</code>関数は以下のようになります。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: haskell; title: ; notranslate">
-- foldrを自分で実装する
myFoldr :: (a -&gt; b -&gt; b) -&gt; b -&gt; &#x5B;a] -&gt; b
myFoldr _ z &#x5B;] = z
myFoldr f z (x:xs) = f x (myFoldr f z xs)
</pre></div>


<p class="wp-block-paragraph">上記の関数において<code>f</code>を<code>(+)</code>、<code>z</code>を<code>0</code>、xsを<code>[1, 2, 3, 4, 5]</code>と考えてどのような動きをしているか考えてみましょう。具体的にどのように処理が流れていくかを記載してみると以下のようになります。</p>


<div class="wp-block-image">
<figure class="aligncenter size-large is-resized"><img decoding="async" width="1024" height="546" src="https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-6-1024x546.png" alt="foldr関数の説明" class="wp-image-503" style="width:700px;height:auto" srcset="https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-6-1024x546.png 1024w, https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-6-300x160.png 300w, https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-6-768x410.png 768w, https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-6.png 1455w, https://haskell-tech.nkhn37.net/wp-content/uploads/2024/03/image-6-1024x546.png 856w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p class="wp-block-paragraph"><code>myFoldr</code>関数についても再帰的に定義されています。「<code>myFoldr f z (x:xs) = f x (myFoldr f z xs)</code>」の部分について着目してみると、リストの先頭要素が前に来て、初期値が後ろにスライドし、残りのリストを使って再度<code>myFoldr</code>が適用されていることが分かるかと思います。</p>



<p class="wp-block-paragraph">このように書き下していくと最終的には「<code>myfoldr (+) 0 []</code>」という形となり、これは「<code>myFoldr _ z [] = z</code>」の定義より初期値<code>z</code>、今回の例では<code>0</code>になります。最終的には、<code>(1 + (2 + (3 + (4 + (5+0)))))</code>のように右から(+)で畳み込まれている計算となっていることが分かるかと思います。</p>



<p class="wp-block-paragraph">上記で見てきた通り<code>foldl</code>関数と<code>foldr</code>関数は、左から畳み込むのか、右から畳み込むのかという点で具体的な動作が異なっています。</p>



<h2 class="wp-block-heading">foldl関数とfoldr関数の違い</h2>



<h3 class="wp-block-heading">適用する関数による結果の違い</h3>



<p class="wp-block-paragraph">上記までで<code>foldl</code>関数と<code>foldr</code>関数を見てきました。足し算<code>(+)</code>を例に見る限りでは、結果は同じでした。しかし、各関数の動作を理解するために動作をステップごとに書いてみましたが「左から畳み込むのか」「右から畳み込むのか」という違いがありました。</p>



<p class="wp-block-paragraph">例えば、適用する関数として引き算<code>(-)</code>を指定した場合には、以下のように結果が大きく変わります。</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: haskell; title: ; notranslate">
-- foldlの場合
minusFoldl :: &#x5B;Int] -&gt; Int
minusFoldl xs = foldl (-) 0 xs

-- foldrの場合
minusFoldr :: &#x5B;Int] -&gt; Int
minusFoldr xs = foldr (-) 0 xs
</pre></div>

<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; gutter: false; title: ; notranslate">
【実行結果例】
ghci&gt; minusFoldl &#x5B;1, 2, 3, 4, 5]
-15
ghci&gt; minusFoldr &#x5B;1, 2, 3, 4, 5]
3
</pre></div>


<p class="wp-block-paragraph">上記の例についても具体的に書き下してみると以下のような計算になっていることが分かります。</p>



<ul class="wp-block-list">
<li><code>minusFoldl</code>の場合：<code>(((((0 - 1) - 2) - 3) - 4) - 5) = -15</code> </li>



<li><code>minusFoldr</code>の場合：<code>(1 - (2 - (3 - (4 - (5 - 0))))) = 3</code></li>
</ul>



<p class="wp-block-paragraph">上記のように畳み込む方向が左からから、右からかという違いがあるため、適用する関数によって大きな違いが出ることに注意が必要です。</p>



<h3 class="wp-block-heading">無限リストに対する挙動の違い</h3>



<p class="wp-block-paragraph">Haskellは遅延評価言語であるため、<code>foldr</code>は無限リストに対しても使用することが可能な場合があります。これは、結果を得るためにリスト全体を評価する必要がないケースで利点となります。</p>



<p class="wp-block-paragraph">一方で、<code>foldl</code>は基本的にリストの全体を評価しようとするため、無限リストには適していません。無限リストに対して<code>foldl</code>を適用すると無限ループとなってしまいます。</p>



<h2 class="wp-block-heading">まとめ</h2>



<p class="wp-block-paragraph">Haskellで畳み込み計算をするための<span class="marker"><strong><code>foldl</code>関数と<code>foldr</code>関数の使い方</strong></span>を解説しました。</p>



<p class="wp-block-paragraph">畳み込みとは、適用する関数、初期値、畳み込み可能な型のデータ(例えばリスト)を受け取って単一の値にする計算のことを言います。<code>foldl</code>関数は左畳み込み、<code>foldr</code>関数は右畳み込みといい、値を畳み込む順序が異なっています。</p>



<p class="wp-block-paragraph">この記事では、<code>foldl</code>関数と<code>foldr</code>関数の各関数の概要と基本的な使い方、そして違いについて説明しました。</p>



<p class="wp-block-paragraph">畳み込み関数(<code>foldl</code>, <code>foldr</code>)は、<code>map</code>関数や<code>filter</code>関数と同様に関数型プログラミングのHaskellにとっては代表的で重要な関数です。しっかりと動作を理解して使いこなせるようにしていただきたいと思います。</p>



<figure class="wp-block-embed is-type-wp-embed is-provider-haskell-tech wp-block-embed-haskell-tech"><div class="wp-block-embed__wrapper">
https://haskell-tech.nkhn37.net/haskell-introduction/
</div></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
					<wfw:commentRss>https://haskell-tech.nkhn37.net/haskell-foldl-foldr-basic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Disk: Enhanced  を使用したページ キャッシュ

Served from: haskell-tech.nkhn37.net @ 2026-06-12 06:06:02 by W3 Total Cache
-->