Fall 2012, David Matuszek

- Get you started programming in Haskell

In the Haskell REPL,` :t `

will tell you the type of *thing*

. Here are some examples:*thing*

Type | Interpretation |
---|---|

`not :: Bool -> Bool` |
`not` is a function that, given a boolean value, returns a boolean value. |

`head :: [a] -> a` |
`head` takes a list of some arbitrary type `a` , and returns a value of type `a` . |

`mod :: Integral a => a -> a -> a` |
`mod` takes two values of type `a` , which must be an `Integral` type, and returns a value of type `a` . |

`map :: (a -> b) -> [a] -> [b]` |
`map` takes a function from `a` to `b` , and a list of `a` , and returns a list of `b` . |

Write the following functions. Where built-in equivalents exist, do not define a function in terms of the equivalent built-in function. For example, don't say

. (You can use `elem`

in other definitions, though.)

The following functions can all be defined in a single line, so try to do so. They do *not* need to work for infinite lists.

`member :: Eq a => a -> [a] -> Bool`

- Returns true if the element occurs in the list.
`count :: (Num a, Eq a1) => a1 -> [a1] -> a`

- Counts the number of times a value occurs in a list.
`forall :: (a -> Bool) -> [a] -> Bool`

- Tests whether all elements of a list satisfy a given condition.
`exists :: (a -> Bool) -> [a] -> Boo`

l- Tests whether any element of a list satisfies a given condition.
`single :: (a -> Bool) -> [a] -> Bool`

- Tests whether exactly one element of a list satisfies a given condition.
`mostly :: (a -> Bool) -> [a] -> Bool`

- True if there are more elements in the list that satisfy the predicate than elements that fail to satisfy the predicate.

`isSet`

and `makeSet`

, you may assume that the lists are "sets," that is, contain no duplicate elements.
`isSet :: Eq a => [a] -> Bool`

- True if the list contains no duplicate elements
`makeSet :: Eq a => [a] -> [a]`

- Remove duplicate elements from a list.
`subset :: Eq a => [a] -> [a] -> Bool`

- True if every element in the first set also occurs in the second set.
`equalSet :: Eq a => [a] -> [a] -> Bool`

- True if the two sets contain the same elements (not necessarily in the same order).
`setDiff :: Eq a => [a] -> [a] -> [a]`

- The set of values that are in the first set but not in the second set.
`setUnion :: Eq a => [a] -> [a] -> [a]`

- The set of values that are in either or both sets.
`setIntersection :: Eq a => [a] -> [a] -> [a]`

- The set of values that are in both sets.

Provide tests for the above functions. Haskell does not come with a testing framework, and I would rather not ask you to download and install one, so here's a very small framework for you to use.

```
assertTrue :: Bool -> String -> IO ()
assertTrue x claim = if x
then putStrLn claim
else putStrLn $ "*** Untrue: " ++ claim
assertFalse :: Bool -> String -> IO ()
assertFalse x claim = assertTrue (not x) claim
assertEqual :: (Eq a, Show a) => a -> a -> IO ()
assertEqual x y = if x == y
then putStrLn $ (show x) ++ " equals " ++ (show y)
else putStrLn $ "*** " ++ (show x) ++ " does not equal " ++ (show y)
```

And here is a brief example of its use:```
main = do
assertTrue (member 3 [1, 2, 3, 4]) "3 is in the list [1, 2, 3, 4]"
assertFalse (member 7 [1, 2, 3, 4]) "7 is not in the list [1, 2, 3, 4]"
assertEqual 3 (count 'a' "abracadabra")
```

There are various measures of "readability"--how good a reader need to be in order to understand a passage of English text. These measures are based on the average length of words (usually measured in syllables) and the average length of sentences (measured in words). The result is usually given as the number of years a child has to have attended school (her grade level) in order to understand the text. These measures are crude, but better than nothing. Your assignment is to let the user read in a passage of text (from a file), apply the formulae, and print out the results.

Your program should read in a sample of text from a file, and use a variation of the Lix index to determine the readability of the text. It basically counts long sentences and big words. (I picked this one because it doesn't require counting syllables!) The formula to apply is:

`words/sentences + 100 * (words >= 6 characters)/words`

where:

- A
**word**is any consecutive sequence of letters, where an apostrophe (`'`

) is considered to be a letter. - To count
**sentences**, just count the number of times one of the characters colon, period, exclamation point, question mark (`: . ! ?`

) appears.

The Haskell function `words`

may be helpful. (There is also an `unwords`

, which you should know about but probably won't need.) However, you will still have to remove punctuation marks from the ends of words in order to count how long they are.

Finally, don't get hung up on the details. The Lix measure isn't rocket science, and I won't care if your results are off by a few percent.

Your program is due before **6am Wednesday, October 17**. Submit via Blackboard.