Monday, March 11, 2013

HASKELL STRINGS AND CHARACTERS

HASKELL STRINGS AND CHARACTERS

REVISED: Friday, February 9, 2024




Haskell Strings and Characters.

I.  HASKELL STRINGS

Because strings are just special kinds of lists, any polymorphic function that operates on lists can also be applied to strings.

A Haskell text string is surrounded by double quotes.

The putStrLn function prints a string.

Prelude>  :type putStrLn
putStrLn :: String -> IO ()

Prelude>  putStrLn "Hello, World!"
Hello, World!
Prelude>  

A text string is a list of individual characters.

Prelude>  let a = ['H', 'e', 'l', 'l', 'o', ',', ' ',  'W', 'o', 'r', 'l', 'd', '!']
Prelude>

Prelude>  a
"Hello, World!"
Prelude>  

Prelude>  :type a
a :: [Char]
Prelude>

The name String is often used instead of [Char] list of characters. String is a synonym or alias for [Char] list of characters.

An empty String is written "", and is a synonym for [].

Regular list operators can be used to construct new strings.

Prelude>  'H' : "askell"
"Haskell"
Prelude>

Haskell's name for the “append” function is (++).  Append is associative. It is more efficient to associate to the right rather than the left. When comparing sequential computing and parallel computing, sequential computing is slower than parallel computing.

Prelude>  "Has" ++ "kell"
"Haskell"
Prelude>  

Prelude>  :t (++)
(++) :: [a] -> [a] -> [a]
Prelude>  

(++) :: [a] -> [a] -> [a]
[] ++ ys        = ys                         -- Empty list.
(x:xs) ++ ys = x : (xs ++ ys))       -- Constructed list.

Prelude>  :t words
words :: String -> [String]
Prelude>

Prelude>  :t unwords
unwords :: [String] -> String
Prelude>

Prelude>  words "Happy birthday little fellow!"
["Happy","birthday","little","fellow!"]
Prelude>

Prelude>  unwords ["Happy","birthday","little","fellow!"]
"Happy birthday little fellow!"
Prelude>  

II.  HASKELL CHARACTERS

A single character is enclosed in single quotes.

A Char value represents a Unicode character.

Prelude>  :info Char
data Char = GHC.Types.C# GHC.Prim.Char# -- Defined in `GHC.Types'
instance Bounded Char -- Defined in `GHC.Enum'
instance Enum Char -- Defined in `GHC.Enum'
instance Eq Char -- Defined in `GHC.Classes'
instance Ord Char -- Defined in `GHC.Classes'
instance Read Char -- Defined in `GHC.Read'
instance Show Char -- Defined in `GHC.Show'
Prelude>  

Haskell represents a text string as a list of Char values, the type “list of Char” is written [Char].

The function rTheyEq has type [Char] and requires two [Char] arguments to create a Bool parameter; however, as shown below the arguments are input as "character strings."

-- C:\Users\Tinnel\rTheyEq.hs

import Data.List
import System.IO

rTheyEq :: [Char] -> [Char] -> Bool
rTheyEq [] [] = True
rTheyEq (x:xs) (y:ys) = x == y && rTheyEq xs ys
rTheyEq _ _ = False

Prelude> :l rTheyEq
[1 of 1] Compiling Main            ( rTheyEq.hs, interpreted )

Ok, modules loaded: Main.
Prelude>

Prelude> rTheyEq "Yes" "No"
False
Prelude>

III. HASKELL ESCAPE CHARACTERS

A. \n NEW LINE

Prelude>  putStrLn "Line 1 \nLine 2"
Line 1 
Line 2                                                          -- New line!
Prelude>

unlines takes a list, and returns it interleaved with newlines \n.

Prelude>  unlines ["aa","bb","cc","dd","ee"]
"aa\nbb\ncc\ndd\nee\n"
Prelude>

lines is the reverse of unlines.

Prelude>  lines "aa\nbb\ncc\ndd\nee\n"
["aa","bb","cc","dd","ee"]
Prelude>

B. \t TAB

Prelude>  putStrLn "Line 1\n\tLine 2"
Line 1 
     Line 2                                                    -- New line with a tab.
Prelude>  

IV. HASKELL SHORTCUT

Save the following as sumNQuickCheck.hs

import Test.QuickCheck

prop_sum :: Integer -> Property

prop_sum n = n >= 0 ==> sum [1..n] == n * (n+1) `div` 2

Then open GHCi; import Test.QuickCheck; :load sumNQuickCheck; and run quickCheck prop_sum as shown below:

Prelude>  import Test.QuickCheck
Prelude>

Prelude>  :load sumNQuickCheck
[1 of 1] Compiling Main             ( sumNQuickCheck.hs, interpreted )
Ok, modules loaded: Main.
Prelude>

Prelude>  quickCheck prop_sum
+++ OK, passed 100 tests.
Prelude>  

The above is QuickCheck's proof that the output of the two functions is the same.

This is an example of asymptotic analysis where a linear function's output is compared to a quadratic function's output. Even though their output is the same; you should always program with linear functions.

V. CONCLUSION

Learning to use Haskell strings and characters will help you all during your career.

VI. REFERENCES

Bird, R. (2015). Thinking Functionally with Haskell. Cambridge, England: Cambridge University Press.

Davie, A. (1992). Introduction to Functional Programming Systems Using Haskell. Cambridge, England: Cambridge University Press.

Goerzen, J. & O'Sullivan, B. &  Stewart, D. (2008). Real World Haskell. Sebastopol, CA: O'Reilly Media, Inc.

Hutton, G. (2007). Programming in Haskell. New York: Cambridge University Press.

Lipovača, M. (2011). Learn You a Haskell for Great Good!: A Beginner's Guide. San Francisco, CA: No Starch Press, Inc.

Thompson, S. (2011). The Craft of Functional Programming. Edinburgh Gate, Harlow, England: Pearson Education Limited.