I'm new to Haskell. I've put together a basic Caesar Cipher, it works, but it's very messy and difficult to read.
caesarCipher :: Int -> String -> String
caesarCipher n xs = [shift n x | x <- xs]
shift n c = num2let ((let2num c + n) `mod` 26)
alphabet = ['a'..'z']
let2num c = head[ b | (a,b) <- zip alphabet [0..length alphabet], a==c]
num2let = (!!) alphabet
What is the "correct" way in Haskell to format functions that consist of multiple variables and expressions, and should I be considering the scope of the variables? And other than efficiency based suggestions have I made any other "major" mistakes?
This is my attempt:
caesarCipher n xs = let
shift n c = num2let ((let2num c + n) `mod` 26) where
alphabet = ['a'..'z']
let2num c = head[ b | (a,b) <- zip alphabet [0..length alphabet], a==c]
num2let = (!!) alphabet
in [shift n x | x <- xs]
I would first of all rewrite some functions. For example. zip alphabet [0 .. length alphabet]
can be replaced with zip alphabet [0..]
, since the zip
will stop from the moment one of the lists is exhausted. Making use of (!!)
and head
is often not good practice, since these functions are non-total: if the index is too large, or the list is empty, (!!)
and head
will error respectively.
We can define helper functions, for example for num2let
:
import Data.Char(chr, ord)
num2let :: Int -> Char
num2let n = chr (n + ord 'a')
here num2let
will map 0
to 'a'
, 1
to 'b'
, etc.
let2num
can be done in a similar manner:
import Data.Char(ord)
let2num :: Char -> Int
let2num c = ord c - ord 'a'
So now we can define caesarCipher
as:
caesarCipher :: Int -> String -> String
caesarCipher n = map (num2let . (`mod 26`) . (n+) . let2num)
So that would look in full as:
import Data.Char(chr, ord)
num2let :: Int -> Char
num2let n = chr (n + ord 'a')
let2num :: Char -> Int
let2num c = ord c - ord 'a'
caesarCipher :: Int -> String -> String
caesarCipher n = map (num2let . (`mod` 26) . (n+) . let2num)
The nice thing is that you can here reuse the let2num
and num2let
for other functions.
Normally top-level functions are separated with a blank line, and are given a signature. This is not necessary , but makes it usually more convenient to read.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.