在Haskell中使用vigenere密码编码文本时遇到问题

时间:2013-02-27 19:53:35

标签: haskell encryption vigenere

我正在编写一个编码项目,我们需要在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)。我不知道如何解决这个问题,更不用说如何实际让程序检查/更改每个索引上的字母,就像我想要的那样。有人可以帮忙吗?

2 个答案:

答案 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扩展 - 所以一定要使用它!只是觉得我会用一种漂亮而紧凑的方式来写它。