<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: AlexMaryW</title>
    <description>The latest articles on DEV Community by AlexMaryW (@alexmaryw).</description>
    <link>https://dev.to/alexmaryw</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1913364%2Ff30b70e2-f7de-4a53-8c87-3e901d0c20cc.png</url>
      <title>DEV Community: AlexMaryW</title>
      <link>https://dev.to/alexmaryw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexmaryw"/>
    <language>en</language>
    <item>
      <title>How to Split Audiobooks into Chapters for Free Using Chapterize-Audiobooks?</title>
      <dc:creator>AlexMaryW</dc:creator>
      <pubDate>Tue, 22 Oct 2024 16:40:17 +0000</pubDate>
      <link>https://dev.to/alexmaryw/how-to-split-audiobooks-into-chapters-for-free-using-chapterize-audiobooks-4jg1</link>
      <guid>https://dev.to/alexmaryw/how-to-split-audiobooks-into-chapters-for-free-using-chapterize-audiobooks-4jg1</guid>
      <description>&lt;p&gt;&lt;strong&gt;If you’re tired of dealing with large MP3 files and want to learn how to split audiobooks into chapters for free, this step-by-step guide will show you how to use Chapterize-Audiobooks effectively.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you've ever purchased an audiobook only to find one huge mp3 file, you know how frustrating it can be. I’ve been there. Every time I restarted the app, I’d be thrown back to the beginning, struggling to find my place. It was such a headache that I eventually gave up on the book altogether.&lt;/p&gt;

&lt;p&gt;Fortunately, there's a solution to this headache - &lt;strong&gt;Chapterize-Audiobooks&lt;/strong&gt;! This open-source audiobook splitter available on GitHub allows you to easily convert one large MP3 file into chapterized MP3s. As a beginner, I faced some challenges while installing it, but with this tutorial, you’ll be able to split your audiobooks with ease.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/patrickenfuego/Chapterize-Audiobooks" rel="noopener noreferrer"&gt;Chapterize-Audiobooks&lt;/a&gt; is an open-source program with a command line interface that can split one big MP3 audiobook file into easy-to-navigate chapterized MP3s. Because this program is &lt;em&gt;open source&lt;/em&gt;, it's available for free. &lt;em&gt;Command line interface&lt;/em&gt;, on the other hand, means that you need to write instructions for the program in the &lt;em&gt;terminal&lt;/em&gt; (&lt;strong&gt;Command Prompt&lt;/strong&gt; application on Windows). Your instructions will have to follow a special syntax so that the software can understand and execute them. &lt;/p&gt;

&lt;p&gt;Don't worry if you’re unfamiliar with these terms! This tutorial will walk you through the process step-by-step so you can effortlessly split your audiobooks into chapters.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Install Python, Git, and FFmpeg for Splitting Audiobooks
&lt;/h2&gt;

&lt;p&gt;To use Chapterize-Adiobooks, you will need to install three things on your computer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a programming language called &lt;em&gt;Python&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;a tool for managing code called &lt;em&gt;Git&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;and an audio processing tool called &lt;em&gt;ffmpeg&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Let's begin with Python because it's the easiest one to install.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Open the terminal on your computer (Command Prompt application on Windows). The first thing you'll see in your terminal is a &lt;em&gt;prompt&lt;/em&gt;* and it will look like this: &lt;code&gt;C:\Users\your-username&amp;gt;&lt;/code&gt;. To check if Python is installed on your computer, type/copy the following line into your terminal and hit enter:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;small&gt;&lt;strong&gt;This line is a great example of the syntax you need to use to execute a program in the terminal. Usually, the program's name comes first and, then, your chosen options/parameters separated by spaces.&lt;/strong&gt;&lt;/small&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If Python is already set up on your computer, the terminal will display its version (e.g. Python 3.12.6) and you can move to installing Git.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you don't have Python on your computer, Windows 10 will open Microsoft Store for you. There, you can download and install Python free of charge. When the installation's complete, type/copy the following line into your terminal and hit enter:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the terminal displays Python's version (e.g. Python 3.12.6), the installation has been successful. &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Now that we have Python, let's install Git.&lt;/strong&gt; &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You can get the Git installer for free from &lt;a href="https://git-scm.com/downloads/win" rel="noopener noreferrer"&gt;Git's official website&lt;/a&gt;. &lt;/li&gt;
&lt;li&gt;When the download is finished, click on the file, and go through the installation process (you can safely keep clicking "Next" until the "Install" button appears). &lt;/li&gt;
&lt;li&gt;Once Git is installed, restart your terminal before moving forward with this tutorial.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Two done, one to go! Here's how you install  ffmpeg.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download the zip file with source code for ffmpeg by clicking &lt;a href="https://www.gyan.dev/ffmpeg/builds/ffmpeg-git-full.7" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Unpack the file. To do this you can use &lt;a href="https://www.7-zip.org/download.html" rel="noopener noreferrer"&gt;7zip program&lt;/a&gt; or &lt;a href="https://www.win-rar.com/start.html?&amp;amp;L=0" rel="noopener noreferrer"&gt;WinRAR&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Rename the unpacked folder to "ffmpeg".&lt;/li&gt;
&lt;li&gt;Move the "ffmpeg" folder to your C drive. To find your C drive, you can type into your computer search bar "This PC", click it, and find "Windows (C:)" in the "Devices and drives" section.&lt;/li&gt;
&lt;li&gt;Search for the Command Prompt application, right-click it, and select "Run as administrator" from the drop down menu. &lt;/li&gt;
&lt;li&gt;When the terminal opens, your prompt should look like this: &lt;code&gt;C:\WINDOWS\system32&amp;gt;&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now we need to add ffmpeg's installation folder to the system's PATH so that Windows knows where to find ffmpeg when it's needed. To do that, type/copy the following line into your terminal and hit enter:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;setx /m PATH &lt;span class="s2"&gt;"C:&lt;/span&gt;&lt;span class="se"&gt;\f&lt;/span&gt;&lt;span class="s2"&gt;fmpeg&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="s2"&gt;in;%PATH%"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you were successful, the terminal will display the following message: "SUCCESS: Specified value was saved". To proceed, you need to restart your computer. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When your computer restarts, you can double-check if ffmpeg is set up. To do so, run Command Prompt app as an administrator, type/copy the following line into your command line, and hit enter:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the installation was successful, the terminal will display ffmpeg's version, configuration, and libraries.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Great job! You're all set up to install Chapterize-Audiobooks!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;small&gt;*The prompt will reappear at the beginning of new line in your terminal when your computer has executed your command. For the sake of brevity, the prompt is omitted in the command lines in this tutorial. The prompt will no longer reappear when we start using Chapterize-Audiobooks.&lt;/small&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Install Chapterize-Audiobooks
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;To install Chapterize-Audiobooks, you need to download the program from GitHub. Type/copy the following line into your terminal and hit enter:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/patrickenfuego/Chapterize-Audiobooks.git
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;small&gt;&lt;strong&gt;This line copies the program's code from GitHub to your computer and you can use it to download any open source program. Please make sure to copy the correct GitHub link into your command.&lt;/strong&gt;&lt;/small&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When the prompt reappears in the terminal, it means the download was successful and we can proceed by going into the program's folder. Type/copy the following line into your terminal and hit enter:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd Chapterize-Audiobooks
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When the prompt reappears in this form: &lt;code&gt;C:\Users\your-username\Chapterize-Audiobooks&amp;gt;&lt;/code&gt;, it means you have entered the correct folder on your computer. The next step is installing libraries necessary for Chapterize-Audiobooks to run correctly  (listed in the "requirements.txt" file). A program called Pip* will handle this process by reading the file and installing the libraries included in it. To complete this step, type/copy the following line into your terminal and hit enter:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Congratulations! You have installed Chapterize-Audiobooks and are ready to split your audiobooks!&lt;/p&gt;

&lt;p&gt;&lt;small&gt;*Pip is installed together with Python so it's already set up on your computer. &lt;/small&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Use Command Line to Split Audiobooks
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Whenever you'd like to split an audiobook using Chapterize-Audiobooks, you need to first go into the program's folder. You can do this by typing/copying the following line into your terminal and hitting enter (if you have just installed the program, you're already in the correct folder and can move to step 3):&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd Chapterize-Audiobooks
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When the prompt reappears in the following form: &lt;code&gt;C:\Users\your-username\Chapterize-Audiobooks&amp;gt;&lt;/code&gt;, it means you have entered the folder and are ready to split your audiobook.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;To split an audiobook, we need the audiobooks's &lt;em&gt;file path&lt;/em&gt;, its location on your computer. The program will split your audiobook faster if the file is saved on your computer rather than on a peripheral device like a USB, memory card, etc. Although Windows doesn't provide the file path, here's how you can put it together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Right-click your audiobook's folder, choose "Properties", and copy the address shown in the "Location" section. &lt;/li&gt;
&lt;li&gt;Add your audiobook file's name with ".mp3" at the end of the file path, e.g. &lt;code&gt;C:\Users\your-username\Desktop\audiobook\audiobook.mp3&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;If your audiobook's name contains spaces, replace them with hyphens (e.g. my-audiobook.mp3), or the terminal will misinterpret them.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Now, you're all set to split the audiobook. To use the Chapterize-Audiobooks program, your command line will have to include &lt;code&gt;python&lt;/code&gt; (tells the terminal to use Python to run the program), &lt;code&gt;chapterize_ab.py&lt;/code&gt; (the program file), and the audiobook's file path in single quotation marks (use the quotation marks, to avoid issues if your file path contains spaces). To split the audiobook, type the following line into your terminal, paste your file path, and hit enter:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  python chapterize_ab.py 'C:\Users\your-username\Desktop\audiobook\audiobook.mp3'
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Now, the program will do its magic and split your monolithic MP3 into chapterized MP3 files. Please be patient with this process because the longer your audiobook, the longer the program will take to chapterize it (it might take an hour or more in certain cases).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  How to Add Titles, Cover Art, etc., with Chapterize-Audiobooks
&lt;/h2&gt;

&lt;p&gt;Chapterize-Audiobooks can do more than just split your audiobook. You can, for example, ask it to give your audiobook a title, add a cover art, or author's name. All available parameters can be found in the &lt;a href="[#usage](https://github.com/patrickenfuego/Chapterize-Audiobooks?tab=readme-ov-file#usage)"&gt;Usage&lt;/a&gt; and &lt;a href="https://github.com/patrickenfuego/Chapterize-Audiobooks?tab=readme-ov-file#examples" rel="noopener noreferrer"&gt;Examples&lt;/a&gt; sections of Chapterize-Audiobooks's readme. &lt;/p&gt;

&lt;p&gt;The parameters in square brackets are optional and parameters in curly brackets are available options to choose from. You can add as many as you like and in an order that suits you by typing them together with the command line splitting the audiobook. For example, typing the following line and hitting enter will split an audiobook, add cover art to it, and the author's name:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python chapterize_ab.py 'your audiobook path' --title 'your audiobook's title' --cover_art 'path to the cover art' --author 'author's name'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;Was this guide helpful? Do let me know in the comments and enjoy your chapterized audiobooks! 😃&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>splitmp3audiobooks</category>
      <category>howtosplitaudiobooks</category>
      <category>freeaudiobooksplitter</category>
      <category>chapterizeaudiobooks</category>
    </item>
    <item>
      <title>Indexable Containers in Haskell</title>
      <dc:creator>AlexMaryW</dc:creator>
      <pubDate>Sun, 11 Aug 2024 11:12:24 +0000</pubDate>
      <link>https://dev.to/alexmaryw/indexable-containers-in-haskell-95m</link>
      <guid>https://dev.to/alexmaryw/indexable-containers-in-haskell-95m</guid>
      <description>&lt;p&gt;While learning Haskell, you will come across &lt;code&gt;List&lt;/code&gt;, the most popular indexable &lt;a href="https://en.wikipedia.org/wiki/Container_(abstract_data_type)" rel="noopener noreferrer"&gt;container&lt;/a&gt; available in this programming language. However, as you dive deeper into Haskell,  &lt;code&gt;List&lt;/code&gt;'s limitations, e.g. slow indexing or immutability, will become more and more pervasive. Although we cannot fix &lt;code&gt;List&lt;/code&gt;'s flaws, we can use alternative modules to achieve better performance and/or functionality. In this post, we will discuss &lt;code&gt;List&lt;/code&gt; and two modules you can use instead, &lt;code&gt;Data.Array&lt;/code&gt; and &lt;code&gt;Data.Vector&lt;/code&gt;, aiming to collect essential knowledge on them in one place and differentiate between them. &lt;/p&gt;

&lt;h2&gt;
  
  
  List
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://hackage.haskell.org/package/base-4.20.0.1/docs/Data-List.html" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;List&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; is one of the most basic data structures in every programming language and, if Haskell isn't your first programming language, you might already be familiar with it. Yet, Haskell's built-in &lt;code&gt;List&lt;/code&gt; is rather special for three reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firstly, it can contain exclusively same-type elements (contrary to, e.g., lists in Python).&lt;/li&gt;
&lt;li&gt;Secondly, it has performance characteristics of &lt;strong&gt;linked lists&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Lastly, as everything in Haskell, it is immutable.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;longList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;50000&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;-- A List of 50,000 elements&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;elemAt50000&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;longList&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt; &lt;span class="mi"&gt;50000&lt;/span&gt; &lt;span class="c1"&gt;-- Indexing into the last, 50,000th element (the operation is slow!)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;elemAt50000&lt;/span&gt;
&lt;span class="mi"&gt;50000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;strong&gt;Listing 1: Creating a &lt;code&gt;List&lt;/code&gt; containing 50,000 elements and indexing into the last element&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Indexing into &lt;code&gt;List&lt;/code&gt; can be slow  because the program iterates from the first element to find the desired element. Interestingly, &lt;code&gt;List&lt;/code&gt; can generate values as you index into it. This is caused by Haskell's being lazy and not evaluating elements until you try to read the value.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;infiniteList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;-- Creating an infinite List (you can do this because Haskell is a lazy programming language)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;thisEvaluatesMillionElements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;longList&lt;/span&gt; &lt;span class="o"&gt;!!&lt;/span&gt; &lt;span class="mi"&gt;1000000&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;thisEvaluatesMillionElements&lt;/span&gt;
&lt;span class="mi"&gt;1000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;strong&gt;Listing 2: Creating an infinite &lt;code&gt;List&lt;/code&gt; containing 50,000 elements and indexing into the last element&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;List&lt;/code&gt; is convenient to use because of its simplicity but performing certain operations on it is much more complicated than it would be for an &lt;code&gt;Array&lt;/code&gt; or a &lt;code&gt;Vector&lt;/code&gt;, e.g. copying. Hence, compared to the other two, &lt;code&gt;List&lt;/code&gt; is slow and best suited for simpler purposes. You can use &lt;code&gt;List&lt;/code&gt; if you don't need immediate access to each element, want to iterate from the first element, to avoid any additional dependencies, or to iterate on an infinite number of elements. &lt;/p&gt;

&lt;h2&gt;
  
  
  Array
&lt;/h2&gt;

&lt;p&gt;In contrast to &lt;code&gt;List&lt;/code&gt;, &lt;strong&gt;&lt;a href="https://hackage.haskell.org/package/array-0.5.7.0" rel="noopener noreferrer"&gt;&lt;code&gt;Array&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; is a mutable data structure (except immutable &lt;code&gt;IArray&lt;/code&gt;) that allows immediate access to its elements. Its main advantage is the amount of control it gives you over indexing. For example, you can index into &lt;code&gt;Array&lt;/code&gt; by &lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;Int32&lt;/code&gt;, &lt;code&gt;Int64&lt;/code&gt;, and even &lt;code&gt;Char&lt;/code&gt;. Furthermore, it supports lower and upper bounds, meaning you can assign any position to its first element. Hence, the first element can hold the 5th position and to access it you would have to index into 5. Another advantage &lt;code&gt;Array&lt;/code&gt; has over &lt;code&gt;List&lt;/code&gt; is &lt;a href="https://hackage.haskell.org/package/array-0.5.7.0/docs/Data-Array-Storable.html" rel="noopener noreferrer"&gt;&lt;code&gt;StorableArray&lt;/code&gt;&lt;/a&gt;, a type that can be used with C functions and is available in the &lt;code&gt;Array&lt;/code&gt; module.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Array&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;listArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!!&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;listArray&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="s"&gt;"abcde"&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Array&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt; &lt;span class="kt"&gt;Char&lt;/span&gt; &lt;span class="c1"&gt;-- Creating an Array of Chars, indexed by Ints&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="sc"&gt;'b'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;charArr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;array&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sc"&gt;'c'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="sc"&gt;'a'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"I'm at index a"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'b'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"I'm at index b"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="c1"&gt;-- Creating an Array of Strings, indexed by Chars&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;charArr&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="sc"&gt;'b'&lt;/span&gt;
&lt;span class="s"&gt;"I'm at index b"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;strong&gt;Listing 3: Creating and reading &lt;code&gt;Array&lt;/code&gt;s with various index ranges and types&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;However, &lt;code&gt;Array&lt;/code&gt;'s advantages also lead to its disadvantages. Because &lt;code&gt;Array&lt;/code&gt; grants you control over indexing, you cannot simply create an &lt;code&gt;Array&lt;/code&gt;, you have to define its indexing as well. It is reasonable, then, that if you're working with an already existing &lt;code&gt;Array&lt;/code&gt;, you need to always keep in mind which indexing types it implements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;arr&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;***&lt;/span&gt; &lt;span class="kt"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Ix&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;Index&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;charArr&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;interactive&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;:&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
    &lt;span class="err"&gt;•&lt;/span&gt; &lt;span class="kt"&gt;Couldn't&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="kt"&gt;Char&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt; &lt;span class="kr"&gt;type&lt;/span&gt; &lt;span class="err"&gt;‘&lt;/span&gt;&lt;span class="kt"&gt;Int&lt;/span&gt;&lt;span class="err"&gt;’&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;strong&gt;Listing 4: Examples of incorrect indexing into an &lt;code&gt;Array&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Combining mutability and &lt;em&gt;O(1)&lt;/em&gt; indexability, &lt;code&gt;Array&lt;/code&gt; is a powerful container and can serve complex purposes. It is also built into Haskell and recommended if you consider additional dependencies less than desirable.&lt;/p&gt;

&lt;p&gt;If you want to learn more about &lt;code&gt;Array&lt;/code&gt;, &lt;a href="https://mmhaskell.com/data-structures/array" rel="noopener noreferrer"&gt;this tutorial on MMHaskell&lt;/a&gt; might be helpful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vector
&lt;/h2&gt;

&lt;p&gt;As a data structure, &lt;strong&gt;&lt;code&gt;Vector&lt;/code&gt;&lt;/strong&gt; combines the best qualities of &lt;code&gt;List&lt;/code&gt; and &lt;code&gt;Array&lt;/code&gt;: a simple API and &lt;em&gt;O(1)&lt;/em&gt; access to elements. Similarly to &lt;code&gt;List&lt;/code&gt;, &lt;code&gt;Vector&lt;/code&gt; is immutable (except for &lt;code&gt;MVector&lt;/code&gt; which you can read on &lt;a href="https://hackage.haskell.org/package/vector-0.13.1.0/docs/Data-Vector-Mutable.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;) and can be indexed only by &lt;code&gt;Int&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Vector&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fromList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;let&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fromList&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;vec&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;strong&gt;Listing 5: Creating a &lt;code&gt;Vector&lt;/code&gt; from a &lt;code&gt;List&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;However, &lt;code&gt;Vector&lt;/code&gt; has features that distinguish it from &lt;code&gt;List&lt;/code&gt; and &lt;code&gt;Array&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it is growable, meaning that you can append elements to a &lt;code&gt;Vector&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;it supports loop fusion, which increases its efficiency (&lt;a href="https://markkarpov.com/tutorial/ghc-optimization-and-fusion#fusion" rel="noopener noreferrer"&gt;Mark Karpov has explained this process well in his blog&lt;/a&gt;).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight haskell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;Data.Vector.Mutable&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;grow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;mvec&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt; &lt;span class="kt"&gt;IO&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;MVector&lt;/span&gt; &lt;span class="kt"&gt;RealWorld&lt;/span&gt; &lt;span class="kt"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;-- Creating a Vector of Chars&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="n"&gt;mvec&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="sc"&gt;'x'&lt;/span&gt;
&lt;span class="o"&gt;***&lt;/span&gt; &lt;span class="kt"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="kr"&gt;of&lt;/span&gt; &lt;span class="n"&gt;bounds&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;grown&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;grow&lt;/span&gt; &lt;span class="n"&gt;mvec&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;                        &lt;span class="c1"&gt;-- Growing the Vector by 30 elements&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Vector&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;Mutable&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt; &lt;span class="n"&gt;grown&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
&lt;span class="sc"&gt;'x'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;span&gt;&lt;strong&gt;Listing 6: Mutating and growing a &lt;code&gt;Vector&lt;/code&gt;&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Please note that &lt;code&gt;Vector&lt;/code&gt; is not built into Haskell. The package is available on &lt;a href="https://hackage.haskell.org/package/vector-0.13.1.0" rel="noopener noreferrer"&gt;Hackage&lt;/a&gt;. Just like &lt;code&gt;Array&lt;/code&gt;, the &lt;code&gt;Vector&lt;/code&gt; module offers a &lt;a href="https://hackage.haskell.org/package/vector-0.13.1.0/docs/Data-Vector-Storable.html" rel="noopener noreferrer"&gt;Data.Vector.Storable&lt;/a&gt; that is compatible with C functions. &lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;Vector&lt;/code&gt; is recommended if you need &lt;code&gt;Array&lt;/code&gt;'s &lt;em&gt;O(1)&lt;/em&gt; access, don't mind extra dependencies and lack of generic indexing, and want to perform actions too complex for lists or are looking for a mutable container (only when using &lt;code&gt;MVector&lt;/code&gt; interface).&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Familiarizing yourself with the containers available in a given programming language is a necessary aspect of the learning process. This post gathers the basic information on all three indexable Haskell containers, each with a different purpose, and possibly useful for your project. The table below summarizes the most important features of containers discussed in this post:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;List&lt;/th&gt;
&lt;th&gt;Array&lt;/th&gt;
&lt;th&gt;Vector&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Difficulty&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;low&lt;/td&gt;
&lt;td&gt;high&lt;/td&gt;
&lt;td&gt;medium&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Built-In&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;yes&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mutable&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;yes &lt;br&gt; (except &lt;code&gt;IArray&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;no &lt;br&gt; (except &lt;code&gt;MVector&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Indexable &lt;br&gt;  by&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;e.g. &lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;Word32&lt;/code&gt;, &lt;br&gt; &lt;code&gt;Bool&lt;/code&gt;, or &lt;code&gt;Char&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Int&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Happy coding!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>haskell</category>
      <category>containers</category>
      <category>datastructures</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
