I wrote the following that tries to crack a message that was encrypted via a simple Caesar cipher through brute force. I'm fairly new to Haskell, so any and all input is appreciated.
Because there are infinite ways that something could have been encrypted, it assumes very simple "offset" encryption; like what
decShift uses. It also doesn't assume any "wrapping" if an offset character goes out of range.
It works fine (from my testing), I'd just like any input on how it could be made more readable, idiomatic, or generally better.
simpDec "Encrypted Message", which returns a list of tuples where the first element is the key used to obtain the decryption, and the second is the decrypted message (it returns a list because it's possible for it to return more then one possible decryption).
decUpper = 127 --Upperbound of normal characters decLower = 32 --Lowerbound of normal characters decRange = decUpper - decLower --Total range type Message = String --Checks if the char is in range isInRange :: Char -> Bool isInRange char = ichar <= decUpper && ichar >= decLower where ichar = ord char --Makes sure all chars in the Message are in range isPossible :: Message -> Bool isPossible  = False isPossible m = null [letter | letter <- m, not $ isInRange letter] --Returns a list > 0 if it finds consecutive symbols conSymList :: Message -> Char -> [Char] conSymList  _ =  conSymList (x:xs) lastChar | isSym x && isSym lastChar = x : conSymList xs x | otherwise = conSymList xs x where isSym c = isSymbol c || isPunctuation c --Checks if a string has 2 symbols beside each other (meaning its improbable) isProbable :: Message -> Bool isProbable  = False isProbable m = null $ conSymList m 'a' --Shifts all characters by n decShift :: Message -> Int -> Message decShift  _ =  decShift (x:xs) n | iNewChar > 0 = chr iNewChar : decShift xs n | otherwise = x : decShift xs n where iNewChar = ord x + n --Returns a list of tuples of the offset used, and the shifted Message getCombos :: Message -> [(Int,Message)] getCombos m = [(off,decShift m off) | off <- [decRange * (-1)..decRange]] --Returns a list of tuples of possible decryptions (KeyUsed,Message) simpDec :: Message -> [(Int, Message)] simpDec m = [(key,try) | (key,try) <- getCombos m, isPossible try && isProbable try]