我正在编写一个编码项目,我们需要在Haskell中编写一个vigenere cypher。我花了好几个小时并没有取得什么进展,但我坚持一个特定的部分。到目前为止,这是我的代码:
--Program: VigCipher.hs
--Author: Mouse
import Data.Char
import Text.Printf
--Changes letters to their numerical value
let2int :: Char -> Int
let2int c = ord c - ord 'a'
--Changes numerical values to letters
int2let :: Int -> Char
int2let n = chr (ord 'a' + n)
--Shift letter by n mod 26 places
shift :: Int -> Char -> Char
shift n c | isLower c = int2let ((let2int c + n) `mod` 26)
| otherwise = c
--Encoding function
encode :: String -> String -> [Char]
encode key msg = [shift (26 - let2int (key !! a) | a <- as) (msg !! a) | x <- zip (cycle key)msg]
我的问题在于编码功能:我希望函数检查并更改密钥和应该编码的消息的每个索引处的字符。我的印象是我所拥有的应该工作,但是当我运行它时,我会因为|而得到解析错误in :(关键!! a)| a&lt; - as)。我不知道如何解决这个问题,更不用说如何实际让程序检查/更改每个索引上的字母,就像我想要的那样。有人可以帮忙吗?
答案 0 :(得分:3)
语法是
[element | bindings, guards]
您的语法错误是
|
标志|
发生在元素部分完成之前(计算括号)所以试试
encode key msg = [shift (26 - let2int (key !! a)) (msg !! a)
| a <- as, x <- zip (cycle key) msg]
您的下一个错误是因为您未在任何地方定义as
。 (而且您似乎没有使用x
。)
修改:在评论中,您说您已将代码更改为
encode key msg = [shift (26 - let2int (x)) (msg) | x <- zipWith (fst() key msg)]
你说你很困惑,你收到的错误信息表明你没有给出zipWith
它需要的三个参数。
你给了zipWith
一个参数,它是(fst() key msg)
。
我设想将代码更改为
encode key msg = zipWith f (cycle key) msg
where f keyElem msgElem = shift (26 - let2int keyElem) msgElem
答案 1 :(得分:2)
启用parallel list comprehensions(在您的文件顶部粘贴{-# LANGUAGE ParallelListComp #-}
,或在GHCi中输入:set -XParallelListComp
),您可以写道:
encode key msg = [shift (26 - let2int k) m | k <- cycle key | m <- msg]
这将是卑鄙的
encode key msg = [shift (26 - let2int k) m | (k,m) <- zip (cycle key) msg]
与
相同encode key msg = zipWith (\k m -> shift (26 - let2int k) m) (cycle key) msg
即。 dave4420的解决方案。他的解决方案更具惯用性,并且不依赖于GHC扩展 - 所以一定要使用它!只是觉得我会用一种漂亮而紧凑的方式来写它。