Exercise 5.8

encrypt :: [Char] -> [Char]
encrypt cs = map encChar cs
    where encChar c = toEnum((fromEnum c + 1) `mod` 256)
 
decrypt :: [Char] -> [Char]
decrypt cs = map decChar cs
    where decChar c = toEnum((fromEnum c + 256 - 1) `mod` 256)

The addition of 256 ensures a proper wraparound on decryption. This exercise seemed a bit silly to me: why not have one function to do both, and allow an arbitrary key?

caesar :: [Char] -> Int -> [Char]
caesar cs k = map caesarChar cs
    where caesarChar c = toEnum((fromEnum c + 256 + k) `mod` 256)

4 Responses to “Exercise 5.8”

  1. Examples are allowed to be silly.
    Paul Hudak said that frogs have small brains 🙂

    IMHO
    fromEnum c+256-1 `mod` 256
    is equal to
    fromEnum c-1 `mod` 256
    beacuse
    (a +k ) `mod` k
    is equal to:
    a `mod` k

    My solution:
    shift s x = toEnum (mod (fromEnum x+s) 256)::Char
    encrypt,decrypt:: String->String
    encrypt = map (shift 1)
    decrypt = map (shift (-1))

  2. Mike says:

    c+k mod 256
    in general is not equal to
    c + 256 + k mod 256.

    Consider what happens when c + k is negative. In Python, the mod operator always returns a positive value, but not in Haskell.

  3. This code seems complicated to me..

    how come there are no paramaters to the encrypt and decrypt functions?

    Where does s come from in the shift function?

  4. admin says:

    s is the first parameter to shift – the amount to shift by. Inverting the order of the parameters from my original solution allows a more functional style.

    It looks like there are no parameters to encrypt/decrypt because they are written in point free style.

    See section 9.1 of the book.

Leave a Reply