簡體   English   中英

Haskell無法將預期類型與實際類型匹配

[英]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 (因為我認為是一樣的)
  • 使用模式匹配而不是headtail
    即lst ... head lst ... tail lst-> lst@(c:cs)
    • 那么lst本身是可引用的, 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM