1

我正在从事一个编码项目,我们需要在 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]

我的问题出在 Encoding 函数中:我希望该函数在键和应该编码的消息的每个索引处检查和更改字符。我的印象是我所拥有的应该可以工作,但是当我运行它时,由于 | 在:(键!!a)| 一个 <- 作为)。我不知道如何解决这个问题,更不用说如何让程序像我想要的那样检查/更改每个索引处的字母了。有人可以帮忙吗?

4

2 回答 2

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
于 2013-02-27T20:01:00.027 回答
2

启用并行列表推导(通过粘贴{-# LANGUAGE ParallelListComp #-}在文件顶部,或通过输入:set -XParallelListCompGHCi),您可以编写:

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 扩展 - 所以一定要使用那个!只是想我会展示一种很好且紧凑的编写方式。

于 2013-02-27T22:20:55.837 回答