执行以下代码会导致非穷举模式错误。我无法弄明白为什么。请帮忙。感谢。
module Cipher where
import Data.Char
caesar :: Int -> [Char] -> [Char]
caesar n [] = []
caesar n st = go n st
where go nn (x:xs)
| (x:xs) == [] = []
| ((+nn) $ ord x) > 122 = (chr $ (+nn) 96) : go nn xs
| ((+nn) $ ord x) >= 97 && ((+nn) $ ord x) <=122 = (chr.(+nn) $ ord x) : go nn xs
| otherwise = error "input error"
答案 0 :(得分:3)
我认为错误在于以下几行
where go nn (x:xs)
| (x:xs) == [] = []
匹配(x:xs) == []
永远不会成立,因为第一个总是一个带有(真实)头部和(可能是空的)尾部的列表
你可以通过
解决这个问题 where go _ [] = []
go nn (x:xs) | ((+nn) $ ord x) > 122 = (chr $ (+nn) 96) : go nn xs
| ((+nn) $ ord x) >= 97 && ((+nn) $ ord x) <=122 = (chr.(+nn) $ ord x) : go nn xs
| otherwise = error "input error"
虽然这种风格非常难以辨认 - 我建议从(+nn) $ ord x
更改为ord x + nn
以及chr (ord x + nn)
。
此外,你没有考虑
由于这似乎是一项家庭作业/练习,我不会给出惯用的解决方案,但只提示有一个名为map
的函数,你一定要查找并使用它!
您的函数go
也不是必需的,您可以在没有它的情况下完全编写算法:
caesar :: Int -> String -> String
caesar _ [] = []
caesar n (x:xs)
| 122 < ord x + n = chr (96 + n) : caesar n xs
| 97 <= ord x + n && ord x + n <=122 = chr (ord x + n) : caesar n xs
| otherwise = error "input error"
请用&#34; Alea,iacta esto进行测试!&#34;而不是&#34; foo&#34; - 您将在第一个测试用例中找到更多错误。
解决问题的惯用方法,你有一个列表并使用函数转换每个元素正在使用map
,例如
> map (\x -> x + 3) [1..3]
[4,5,6]
因此你需要一个功能
cipher :: Int -> Char -> Char
cipher n x
| isDigit x = chr $ ord '0' + (ord x - ord '0' + n'') `mod` 10
| isLower x = chr $ ord 'a' + (ord x - ord 'a' + n' ) `mod` 26
| isUpper x = chr $ ord 'A' + (ord x - ord 'A' + n' ) `mod` 26
| otherwise = x
where n' = n `mod` 26 -- for the letters
n'' = n `mod` 10 -- for the digits
caesar :: Int -> String -> String
caesar n xs = map (cipher n) xs
答案 1 :(得分:1)
您的go
函数没有与空列表匹配的案例。 otherwise
后卫在这里没有帮助,因为模式go nn (x:xs)
与之匹配并不匹配。
试试这个:
caesar :: Int -> [Char] -> [Char]
caesar n [] = []
caesar n st = go n st
where go nn (x:xs)
| (x:xs) == [] = []
| ((+nn) $ ord x) > 122 = (chr $ (+nn) 96) : go nn xs
| ((+nn) $ ord x) >= 97 && ((+nn) $ ord x) <=122 = (chr.(+nn) $ ord x) : go nn xs
| otherwise = error "input error"
go _ _ = error "fix me"