Chapter 18
IN THIS CHAPTER
Improving the user interface with sights and sounds
Manipulating data better
Working with algorithms
Haskell supports a broad range of libraries, which is why it’s such a good product to use. Even though this chapter explores a few of the more interesting Haskell library offerings, you should also check out the rather lengthy list of available libraries at http://hackage.haskell.org/packages/
. Chances are that you’ll find a library to meet almost any need in that list.
To store certain kinds of data, you must be able to serialize it — that is, change it into a format that you can store on disk or transfer over a network to another machine. Serialization takes complex data structures and data objects and turns them into a series of bits that an application can later reconstitute into the original structure or object using deserialization. The point is that the data can’t travel in its original form. The binary library (http://hackage.haskell.org/package/binary
) enables an application to serialize binary data of the sort used for all sorts of purposes, including both sound and graphics files. It works on lazy byte strings, which can provide a performance advantage as long as the byte strings are error free and the code is well behaved.
If you find that binary doesn’t quite meet your video or audio processing needs, you can also try the cereal library (http://hackage.haskell.org/package/cereal
). It provides many of the same features as binary, but uses a different coding strategy (strict versus lazy execution). You can read a short discussion of the differences at https://stackoverflow.com/questions/14658031/cereal-versus-binary
.
The Hascore library found at https://wiki.haskell.org/Haskore
gives you the means to describe music. You use this library to create, analyze, and manipulate music in various ways. An interesting aspect of this particular library is that it helps you see music in a new way. It also enables people who might not ordinarily be able to work with music express themselves. The site shows how the library makes lets you visualize music as a kind of math expression.
Of course, some musicians probably think that viewing music as a kind of math is to miss the point. However, you can find a wealth of sites that fully embrace the math in music, such as the American Mathematical Society (AMS) page at http://www.ams.org/publicoutreach/math-and-music
. Some sites, such as Scientific American (https://www.scientificamerican.com/article/is-there-a-link-between-music-and-math/
) even express the idea that knowing music can help someone understand math better, too.
Computer graphics in computers are based heavily in math. Haskell provides a wide variety of suitable math libraries for graphic manipulation, but vect (http://hackage.haskell.org/package/vect
) represents one of the better choices because it’s relatively fast and doesn’t get mired in detail. Plus, you can find it used in existing applications such as the LambdaCube engine (http://hackage.haskell.org/package/lambdacube-engine
), which helps you to render advanced graphics on newer hardware.
All sorts of programming tasks revolve around the use of arrays. The immutable built-in list type is a linked-list configuration, which means that it can use memory inefficiently and not process data requests at a speed that will work for your application. In addition, you can’t pass a linked list to other languages, which may be a requirement when working in a graphics or other scenario in which high-speed interaction with other languages is a requirement. The vector library (http://hackage.haskell.org/package/vector
) solves these and many other issues for which an array will work better than a linked list.
The vector library not only includes a wealth of features for managing data but also provides both mutable and immutable forms. Yes, using mutable data objects is the bane of functional programming, but sometimes you need to bend the rules a bit to process data fast enough to have it available when needed. Because of the nature of this particular library, you should see the need for eager execution (in place of the lazy execution that Haskell normally relies on) as essential. The use of eager processing also ensures that no potential for data loss exists and that cache issues are fewer.
A great many data stores today use JavaScript Object Notation (JSON) as a format. In fact, you can find JSON used in places you might not initially think about. For example, Amazon Web Services (AWS), among others, uses JSON to do everything from creating processing rules to creating configuration files. With this need in mind, you need a library to manage JSON data in Haskell, which is where aeson (http://hackage.haskell.org/package/aeson
) comes into play. This library provides everything needed to create, modify, and parse JSON data in a Haskell application.
Mixed-format data files can present problems. For example, an HTML page can contain both ASCII and binary data. The attoparsec library (http://hackage.haskell.org/package/attoparsec
) provides you with the means for parsing these complex data files and extracting the data you need from them. The actual performance of this particular library depends on how you write your parser and whether you use lazy evaluation. However, according to a number of sources, you should be able to achieve relatively high parsing speeds using this library.
You use the bytestring (http://hackage.haskell.org/package/bytestring
) library to interact with binary data, such as network packets. One of the best things about using bytestring is that it allows you to interact with the data using the same features as Haskell lists. Consequently, the learning curve is less steep than you might imagine and your code is easier to explain to others. The library is also optimized for high performance use, so it should meet any speed requirements for your application.
Unlike many other parts of Haskell, bytestring also enables you to interact with data in the manner you actually need. With this in mind, you can use one of two forms of bytestring calls:
Manipulating strings can be difficult, but you're aided by the fact that the data you manipulate is in human-readable form for the most part. When it comes to byte strings, the patterns are significantly harder to see, and precision often becomes more critical because of the manner in which applications use byte strings. The stringsearch library (http://hackage.haskell.org/package/stringsearch
) enables you to perform the following tasks on byte strings quite quickly:
This library will work with both strict and lazy byte strings. Consequently, it makes a good addition to libraries such as bytestring, which support both forms of bytestring calls. The page at http://hackage.haskell.org/package/stringsearch-0.3.6.6/docs/Data-ByteString-Search.html
tells you more about how this library performs its various tasks.
There are times when the text-processing capabilities of Haskell leave a lot to be desired. The text library (http://hackage.haskell.org/package/text
) helps you to perform a wide range of tasks using text in various forms, including Unicode. You can encode or decode text as needed to meet the various Unicode Transformation Format (UTF) standards.
This library also works with byte strings in both a strict and lazy manner (see the “bytestring” section, earlier in this chapter). Providing this functionality means that the text library can help you in streaming situations to perform text conversions quickly.
The moo library (http://hackage.haskell.org/package/moo
) provides Genetic Algorithm (GA) functionality for Haskell. GA is often used to perform various kinds of optimizations and to solve search problems using techniques found in nature (natural selection). Yes, GA also helps in understanding physical or natural environments or objects, as you can see in the tutorial at https://towardsdatascience.com/introduction-to-genetic-algorithms-including-example-code-e396e98d8bf3?gi=a42e35af5762
. The point is that it relies on evolutionary theory, one of the tenets of Artificial Intelligence (AI). This library supports a number of GA variants out of the box:
The readme (http://hackage.haskell.org/package/moo-1.0#readme
) for this library tells you about other moo features and describes how they relate to the two out-of-the-box GA variants. Of course, the variants you code will have different features depending on your requirements. The single example provided with the readme shows how to minimize Beale’s function (see https://www.sfu.ca/~ssurjano/beale.html
for a description of this function). You may be surprised at how few lines of code this particular example requires.