3

Project Eulerの問題59を解決しようとしています。この問題では、3文字のキー(すべて小文字)を持つメッセージをxor-decryptする必要があります。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

基本的に、キーの1つがメッセージを復号化して「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 に答える