\documentclass[10pt,letterpaper]{article} \usepackage[utf8]{inputenc} \usepackage{listings} \lstnewenvironment{code}{\lstset{language=Haskell,basicstyle=\small}}{} \usepackage{hyperref} \author{Alexander Schaap} \title{Circular Shifter} \begin{document} This module expects lines containing words in a particular order, and creates all possible shifts (moving first word to the end) of those lines. It takes the lines from a storage and enters the shifts into a storage, requiring no order for either; the only storage that needs to be ordered is the one used for lines. Incrementality should not be an issue for this module. The data theoretically does not need to pass through this module if sufficient directions can be given to the (remote) storage. The secret here is how shifting takes place for each storage implementation. Note: Parnas specifies that one long sorted list of shifts of all lines should be the end result. For the purpose of incremental output, shifts for each line are separated into their own storage and sorted separately. He also specified that the circular shifter produces a collection of indices to be used by alphabetizer. However, this shows more of the storage than might be necessary and therefore desirable. \maketitle \begin{code} {-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances #-} module CircularShifter where import LineStorage import qualified Data.IntMap as IntMap class CircularShifter s t r where shift :: (s (t e)) -> (s (r (t e))) rotate :: [a] -> [a] rotate [] = [] rotate (x:xs) = xs ++ [x] rotateAll :: [a] -> [[a]] rotateAll xs = take (length xs) (iterate rotate xs) instance CircularShifter StorageList StorageList StorageList where shift (ListStorage es) = ListStorage $ map shift_ es where shift_ (ListStorage es) = ListStorage $ map ListStorage $ rotateAll es instance CircularShifter StorageMap StorageMap StorageMap where shift m = IntMap.map (toMap . map toMap . rotateAll . IntMap.elems) m where toMap = foldl add IntMap.empty \end{code} \end{document}