3

我正在尝试解决 Project Euler 问题 59,我必须对具有三字符密钥(全小写)的消息进行异或解密。在 ASCII 中,这意味着所有键的集合是

let keys = [[a, b, c] | a <- [97..122], b <- [97..122], c <- [97..122]]

并且以下函数将一起启发式地解密它:

decrypt :: [Int] -> [Int] -> [Char]
decrypt msg xs = map chr $ zipWith xor msg $ (concat . repeat) xs

try :: [[Int]] -> [Int] -> [Char]
try kys msg = head $ filter (isInfixOf "the") $ map (decrypt msg) kys

基本上我一直在尝试密钥,直到其中一个解密消息以在其中包含“the”(我知道该消息具有常见的英文单词)。但是当我绑定keysmessage运行时,try keys message我得到

Couldn't match expected type `Int' with actual type `Integer'
    Expected type: [[Int]]
      Actual type: [[Integer]]
    In the first argument of `try', namely `keys'
    In the expression: try keys message

现在,即使我说它let keys = [map fromIntegral [a, b, c] | a <- [97..122], b <- 97..122],, c <- [97..122]]仍然说它有类型Integer而没有Int,当我尝试时let keys = map (map fromIntegral) keys,以及当我使用时fromInteger。这是怎么回事?

4

1 回答 1

4

问题是类型keys默认为[[Integer]]. 通过在定义时添加类型注释来覆盖它keys

let keys = ... :: [[Int]]

这是因为数字文字的类型(以及 的返回类型fromIntegral)是多态的,所以当您编写let keys = ...态限制时,会启动并将数字类型默认为 ,Integer除非它们以其他方式受到限制。

> let x = 42 
> :t x
x :: Integer
> let y = 42 :: Int
> :t y
y :: Int

另一种解决方案是禁用单态限制。然后将是一个多态值,当您尝试使用它时keys将专门用于该值。[[Int]]

> :set -XNoMonomorphismRestriction
> let x = 42
> :t x
x :: Num b => b
于 2012-10-20T20:38:03.970 回答