我正在尝试解决Project Euler问题59,我必须对具有三个字符键(全部小写)的消息进行xor解密。在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”(我知道该消息有常用的英文单词)。但是当我绑定keys
和message
并运行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
时,以及当我使用{{}时1}}。发生了什么事?
答案 0 :(得分:4)
问题是keys
的类型默认为[[Integer]]
。在定义keys
时添加类型注释来覆盖它:
let keys = ... :: [[Int]]
这是因为数字文字的类型(以及fromIntegral
的返回类型)是多态的,因此当您编写let keys = ...
时,monomorphism restriction会启动并默认数字类型为{ {1}}除非他们以其他方式受到限制。
Integer
另一种解决方案是禁用单态限制。然后> let x = 42
> :t x
x :: Integer
> let y = 42 :: Int
> :t y
y :: Int
将是一个多态值,当您尝试使用它时,它将专门用于keys
。
[[Int]]