Classy Strings

In January we shared many different examples of helpful functions you can use with lists. In Februrary, we'll be focusing on Strings. Of course, Haskell's different string representations all use lists to some extent, so we've already seen several examples of list manipulation being useful with strings. But now we'll look more specifically at the different types that all us to describe string-like data.

Our first useful idea is the IsString class. This can apply to any type that we can derive from a String. The key function is fromString.

class IsString a where
  fromString :: String -> a

Making an instance of this type is easy enough as long as your data makes sense. Suppose we have a simple newtype wrapper for a string.

newtype Person = Person String

Our IsString instance is trivial:

instance IsString Person where
  fromString = Person

But sometimes we might want something a little trickier. Suppose we want to give our person a first AND last name, given only a single string.

data Person = Person
  { firstName :: String
  , lastName :: String
  } deriving (Show)

Now our instance is non-trivial, but still simple if we remember our helpful list functions! We first take all the characters that are "not spaces" to get the first name. Then to get the last name, we drop these characters instead, and then drop all the spaces as well!

instance IsString Person where
  fromString s = Person firstName lastName
    where
      firstName = takeWhile (not . isSpace) s
      lastName = dropWhile isSpace (dropWhile (not . isSpace) s)

We can use this instance in the simple way, applying the fromString function directly:

>> fromString "George Washington" :: Person
Person {firstName = "George", lastName = "Washington"}

But what's more interesting is that if we turn on the "Overloaded Strings" extension, we can use a string literal for this object in our code!

>> :set -XOverloadedStrings
>> let president = "George Washington" :: Person

This compiler extension is extremely useful once we get to other kinds of strings (Text, ByteString, etc.). But, combined with the IsString class, it's a nice little quirk that can make our lives easier in certain circumstances, especially when we are running some kind of parsing program, or pasting in stringified data into our Haskell source when we don't want to bother reformatting it.

We'll be back next Monday with more string tricks! If you want to use tricks like these in a project, you need to learn how to use Stack first. To help with this, sign up for our free Stack mini-course!

Previous
Previous

Line 'em Up!

Next
Next

To Infinity and Beyond!