![](/img/trans.png)
[英]Haskell couldn't match expected type float with actual type 'a'
[英]Haskell couldn't match expected type with actual type
因此,我嘗試使用頻率分析來解密代碼。
import Data.Char
import Data.List
import Data.Function
import qualified Data.Map as DMap
codedMsg = "V'Z GELVAT GB GRNPU GUR PNIRZRA GB CYNL FPENOOYR. VG'F HCUVYY JBEX. GUR BAYL JBEQ GURL XABJ VF 'HAU', NAQ GURL QBA'G XABJ UBJ GB FCRYY VG."
mostFreqLtr = ["E", "T", "A", "O", "I", "N", "S", "H", "R", "D", "L", "C", "U", "M", "W", "F", "G", "Y", "P", "B", "V", "K", "X", "J", "Q", "Z"]
--weed out non alphabetical characters from the list
alphaSort lst
| null lst = []
| isAlpha (head lst) = (head lst) : alphaSort (tail lst)
| otherwise = alphaSort (tail lst)
--sort the list by characters
msgSort [] = []
msgSort lst = sortBy (compare `on` ord) lst
--group each character into it's own list
grp [] = []
grp lst = group lst
--sort the list into most frequent character first
lSort [] = []
lSort lst = reverse (sortBy (compare `on` length) lst)
--change the list into one instance of each character
oneChar [] = []
oneChar lst = take 1 (head lst) : oneChar (tail lst)
--Pairing letters and creating a map of tuples containing frequency related characters
msg = zip (oneChar $ lSort $ grp $ msgSort $ alphaSort $ map toUpper $ codedMsg) mostFreqLtr
msg2 = DMap.fromList msg
--replace coded list with analyzed list
replaceChars lst
| null lst = []
| isAlpha (head lst) = DMap.lookup (head lst) msg2 : replaceChars (tail lst)
| otherwise = (head lst) : replaceChars (tail lst)
result = replaceChars codedMsg
我不斷收到此錯誤:
Couldn't match expected type `Char' with actual type `[Char]'
Expected type: DMap.Map Char a0
Actual type: DMap.Map [Char] [Char]
In the second argument of `DMap.lookup', namely `msg2'
In the first argument of `(:)', namely
`DMap.lookup (head lst) msg2'
在所有頂級函數上編寫類型簽名。 然后你會發現
oneChar :: [[a]] -> [[a]]
同時,我從使用中推測出您的意圖
oneChar :: [[Char]] -> [Char]
您應該使用head
而不是take 1
,或者應該concat
結果以獲得Char
的列表。
msg2
,您構造的映射msg2
具有[Char]
作為鍵,但是您嘗試將其當作具有Char
的鍵來使用。
嗯-我坐下來思考了一下您的代碼
請使用類型簽名,它有助於您大量思考代碼-編譯器也可以優化
給出更有意義的名稱
mostFreqLtr
> freqTable_EN
(很明顯,您正在解密英文文本) alphaSort
> filterAlpha
(當您過濾非字母元素並且不對任何內容進行排序時,這會產生誤導 msgSort
> sort
(因為我認為是一樣的) head
和tail
lst@(c:cs)
c
是其頭部, cs
其尾部(單個元素通常被稱為單個字母,列為帶有s的准復數形式 import Prelude hiding (lookup)
import Data.Char ( isAlpha
, toUpper)
import Data.List ( group
, sort
, sortBy)
import Data.Function (on)
import Data.Map ( fromList
, lookup
, Map)
import Data.Maybe (mapMaybe)
只導入必要的代碼位
codedMsg :: String
codedMsg = "V'Z GELVAT GB GRNPU GUR PNIRZRA GB CYNL FPENOOYR." ++
"VG'F HCUVYY JBEX. GUR BAYL JBEQ GURL XABJ VF 'HAU'," ++
"NAQ GURL QBA'G XABJ UBJ GB FCRYY VG."
freqTable_EN :: [Char]
freqTable_EN = ['E', 'T', 'A', 'O', 'I', 'N', 'S', 'H', 'R'] ++
['D', 'L', 'C', 'U', 'M', 'W', 'F', 'G', 'Y'] ++
['P', 'B', 'V', 'K', 'X', 'J', 'Q', 'Z']
不要使用太長的行-這會使代碼的可讀性降低,姓氏freqTable_EN
很不尋常,但是在這種情況下,我可以隨意偏離標准,因為它可讀性更好。 我還使用[Char]
而不是String
(等效)來使它更清楚地表明它是一個字母表。
-- weed out non alphabetical characters from the list
filterAlpha :: String -> String
filterAlpha = filter isAlpha
-- sort a list by length
sortByLength :: [[a]] -> [[a]]
sortByLength = sortBy (compare `on` length)
-- sort the list into most frequent character first
sortByFreq :: [[a]] -> [[a]]
sortByFreq = reverse . sortByLength
好的函數名不需要這樣的注釋
-- change the list into one instance of each character
reduceGroups :: [[a]] -> [a]
reduceGroups lst = map head lst
你也可以離開lst
東西編譯器足夠聰明來從類型簽名的所有信息,以便最后一行也可能是reduceGroups = map head
-- Pairing coded message with frequency table
pairs :: [(Char, Char)]
pairs = nonAlphaPairs ++ zip freqSortedMsg freqTable_EN
where cleanedMsg = (filterAlpha . map toUpper) codedMsg
freqSortedMsg = (reduceGroups . sortByFreq . group . sort) cleanedMsg
nonAlphaPairs = map (\x ->(x,x)) $ filter (not . isAlpha) codedMsg
(\\x -> (x,x))
是一個lambda表達式,當它們自己被解密時,它簡單地轉換成對的單個字符
-- and creating a map for decryption
cipher :: Map Char Char
cipher = fromList pairs
-- replace encoded text by our cipher
decipher :: String -> String
decipher = mapMaybe (uplook cipher)
where uplook = flip lookup
result :: String
result = decipher codedMsg
main :: IO ()
main = print result
最后一行使您的結果得以打印-正如我們要閱讀的信息;-)隨時詢問是否不清楚。
PS .:我真的很喜歡您的編碼信息-盡管通過頻率分析甚至找不到一個字母。 我只是猜到了您的加密算法。 ( g?
對於vim用戶),我認為您必須使用更長的文本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.