Skip to main content
accumulate
Source Link
Caridorc
  • 28.2k
  • 7
  • 55
  • 138

accumulate

accumulate is a particularly fortunate case because it can be written as flip span using Haskell built-ins (just search String -> (Char -> Bool) -> (String, String) in Hoogle and you will find it (span is more general hence the a in the signature, in your case a = Char))

accumulate

accumulate is a particularly fortunate case because it can be written as flip span using Haskell built-ins (just search String -> (Char -> Bool) -> (String, String) in Hoogle and you will find it (span is more general hence the a in the signature, in your case a = Char))

Source Link
Caridorc
  • 28.2k
  • 7
  • 55
  • 138

Built-ins

The function showTermList applies show to each item in the list (map show) and puts , [COMMA] between any two items of the list (intercalate ","). You can just use this predefined functions to write:

showTermList = intercalate ","  . map show

Also in tokens:

| isSpace c = tokens cs -- eat all whitespace

Eating all white-space is better expressed as filter (not . isSpace).

tokens :: String -> [Token]
tokens = tokens' . filter (not . isSpace)
  where
    tokens' [] = []
    tokens' (c:cs) = let (token, cs') = nextToken (c : cs)
        in token : tokens cs'

Repetition

You have the repetition of (rule, in your function:

parseRule :: [Token] -> (Rule, [Token])
parseRule [] = error "No tokens to parse"
parseRule ts =
    if null ts' || token (head ts') /= dot then
        (rule, ts')
    else
        (rule, tail ts')
    where (rule, ts') = parseRule' ts

You could avoid it by assigning a tail variable:

parseRule ts = (rule, tail)
    where
      (rule, ts') = parseRule' ts
      tail = if null ts' || token (head ts') /= dot then ts' else tail ts'

Guards are even more visually immediate then if else:

parseRule ts = (rule, decideTail ts')
    where
      (rule, ts') = parseRule' ts
      decideTail ts'
        | null ts' || token (head ts') /= dot = ts'
        | otherwise = tail ts'

Now we note that:

(rule, decideTail ts')
     where
       (rule, ts') = parseRule' ts

Is built-in under the name of mapSnd

parseRule ts = mapSnd decideTail $  parseRule' ts
    where
      decideTail ts'
        | null ts' || token (head ts') /= dot = ts'
        | otherwise = tail ts'

Or even pointfree:

parseRule = mapSnd decideTail .  parseRule'
  where
      decideTail ts'
        | null ts' || token (head ts') /= dot = ts'
        | otherwise = tail ts'