The following function clearly has duplication between the two list comprehensions, but how can it be eliminated without increasing the total length of the code? I’ve got a sneaky feeling there’s a nice abstraction lurking here but I just can’t see it…
letterAt :: [Word] -> Int -> Int -> Maybe Char
letterAt wrds x y = listToMaybe $
[wtext !! (x - wx) |
Word wx wy wtext Across <- wrds,
wy == y && x >= wx && x < wx + length wtext] ++
[wtext !! (y - wy) |
Word wx wy wtext Down <- wrds,
wx == x && y >= wy && y < wy + length wtext]
Some background:
The function is taken from a crossword program. The crossword is represented as [Word], where
data Word = Word { startX :: Int,
startY :: Int,
text :: String,
sense :: Sense }
data Sense = Across | Down
The words where sense == Across start at position (startX, startY) and continue in the positive x direction, and those where sense == Down continue in the positive y direction. The aim of the function is to get the character at location (x, y) in a Just, or Nothing if there isn’t a character there.
Feel free to point out any other sins against Haskell I’ve committed here, I’ve just started with the language and still trying to get to grips with it!
Here are some points about your code:
filterwhen want to select certain elements of a list based on the predicate.Data.List.findYour conditions looks symmetric so you can define a
transformfunction asNow writing the code will require writing conditions only once