Haskell维吉尼亚密码vignereCode函数报错原因及解决方法求助
报错原因
- 你定义的
vignereString类型是String -> String -> String,需要传入两个String参数才能得到字符串结果,但你在vignereCode函数里直接把未传参的vignereString传给了需要String输入的encodeString,参数数量不足导致类型不匹配。 - 除此之外代码还存在另外两个隐藏错误:
vignereString的where子句里len = length $ concat写法错误,concat是需要传入可折叠容器的函数,你没有传入目标参数就调用,也会触发类型错误。rightShift和leftShift都传入了(-)函数,加密解密的偏移逻辑完全一致,无法实现正常的加解密功能。
修复方法
- 修正
vignereCode函数,给vignereString传入两个参数:
vignereCode secret plain = encodeString $ vignereString secret plain
- 修正
vignereString的长度计算逻辑,取明文(去除空格后)的长度作为密钥流的截断长度:
vignereString secret plain = take len $ cycle secret where len = length $ concat $ words plain
- 修正偏移逻辑:加密用加法,解密用减法:
rightShift :: Int -> Char -> Char rightShift = shift (+) -- 加密右移加偏移量 leftShift :: Int -> Char -> Char leftShift = shift (-) -- 解密左移减偏移量
完整可运行代码
import Data.Char import Prelude import System.IO encode :: Char -> Int encode x = ord x - ord 'A' decode :: Int -> Char decode x = chr (x + ord 'A') shift :: (Int -> Int -> Int) -> Int -> Char -> Char shift f x ch = decode $ f (encode ch) x `mod` 26 rightShift :: Int -> Char -> Char rightShift = shift (+) leftShift :: Int -> Char -> Char leftShift = shift (-) encodeString :: String -> [Int] encodeString str = map encode str vignereString :: String -> String -> String vignereString secret plain = take len $ cycle secret where len = length $ concat $ words plain vignereCode :: String -> String -> [Int] vignereCode secret plain = encodeString $ vignereString secret plain encrypt :: String -> String -> String encrypt secret plain = zipWith rightShift code plainNoSpace where code = vignereCode secret plain plainNoSpace = concat $ words plain decrypt :: String -> String -> String decrypt secret cipher = zipWith leftShift code cipherNoSpace where code = vignereCode secret cipher cipherNoSpace = concat $ words cipher
内容的提问来源于stack exchange,提问作者Bioshocker
相关产品推荐
相关产品推荐

