2012-10-20 67 views
3

我試圖解決項目歐拉問題59,我必須異或解密具有三個字符的鍵(全部小寫)的消息。在ASCII這將意味着將所有鍵的是Haskell Integer和Int類型;轉換不起作用

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

問題是,keys的類型默認爲[[Integer]]。定義keys時加入類型註釋覆蓋此:

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

這是因爲數字文字的類型(和fromIntegral返回類型)是多態的,所以,當你寫let keys = ...monomorphism restriction踢和違約數字類型爲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 
+0

如果有人在將來閱讀這個問題,請注意'let keys = [[a,b,c] | a < - 來自整數[97..122] :: [Int]的映射,b < - 來自整數[97..122] :: [Int]的映射,c < - 來自整數[97..122]的映射:: [Int] ]'是修正它的確切代碼。另外,感謝哈馬爾,我不知道這種形式的類型轉換。 – jclancy

+4

@jclancy如果爲(至少)一個文字指定了一個'Int'類型,或者爲(至少)一個'[97 .. 122]'列表指定了一個'Int'類型,或者爲[[[ INT]]'''keys',你不需要'fromIntegral'。 –

+0

啊,由於某種原因,以前不適合我,也許是一個錯字。那麼最好的解決方案是'let keys = [[a,b,c] | a < - [97..122],b < - [97..122],c < - [97..122]] :: [[Int]]' – jclancy