2012-04-02 10 views
1

私は失敗する可能性がある関数を持っているので、返す値をMaybeにラップする必要があります。それは失敗する可能性のある別の関数を使用し、それもMaybeでラップされます。問題は中間の計算で型を動かすために、私はMaybeのコンテキストで機能するために関数を "時期尚早に"持ち上げなければならないということです。その結果、私のタイプは「おそらく整数」になります。私が望むのはたぶん[Integer]です。問題の関数はexptDecipherString関数です。 "早すぎる"リフティングを強制する関数はmodularInverse関数です。余分なものを取り除く方法

import Data.Char 
import Control.Applicative 
import Control.Monad 
import Math.NumberTheory.Powers 

--Helpers 

extendedGcd::Integer->Integer->(Integer, Integer) 
extendedGcd a b | r == 0 = (0, 1) 
       | otherwise = (y, x - (y * d)) 
       where 
        (d, r) = a `divMod` b 
        (x, y) = extendedGcd b r 

modularInverse::Integer->Integer->Maybe Integer 
modularInverse n b | relativelyPrime n b = Just . fst $ extGcd n b 
        | otherwise = Nothing 
        where 
         extGcd = extendedGcd 

relativelyPrime::Integer->Integer->Bool 
relativelyPrime m n = gcd m n == 1 

textToDigits::String->[Integer] 
textToDigits = map (\x->toInteger (ord x - 97)) 

digitsToText::[Integer]->String 
digitsToText = map (\x->chr (fromIntegral x + 97)) 

--Exponentiation Ciphers 

exptEncipher::Integer->Integer->Integer->Maybe Integer 
exptEncipher m k p | relativelyPrime k (m - 1) = Just $ powerMod p k m 
        | otherwise = Nothing 

exptDecipher::Integer->Integer->Integer->Maybe Integer 
exptDecipher m q c | relativelyPrime q (m - 1) = Just $ powerMod c q m 
        | otherwise = Nothing 

exptEncipherString::Integer->Integer->String->Maybe [Integer] 
exptEncipherString m k p | relativelyPrime k (m - 1) = mapM (exptEncipher m k) plaintext 
         | otherwise = Nothing 
    where 
     plaintext = textToDigits p 

exptDecipherString::Integer->Integer->[Integer]->Maybe String 
exptDecipherString m k c | relativelyPrime k (m - 1) = fmap digitsToText plaintext 
         | otherwise = Nothing 
    where 
     q = modularInverse k (m - 1) 
     plaintext = mapM (exptDecipher m <$> q <*>) (map pure c) 

答えて

6

「どのようにXがYになることができるか」の最初のことは、hoogleです。この場合、joinを使用することをお勧めします。Maybeを1つにまとめます。

一部のコード再構成では、Maybeモナドを使用してここで手助けすることもできます。

他のすべてが失敗した場合は、関数を使用する独自のソリューションまたはパターンマッチングのcase文をロールバックします。

+0

私はHoogleを試しましたが、多分私はそれをどのように使用するかについて愚かではありません。私は「Monad m => m m a-> m a」とかそのようなものを入力しました。私はまだタイプの考え方を理解しようとしています:( –

+3

@JoshInfiestoあなたの質問はほぼ正しいです!あなたはちょっと括弧を忘れてしまったのですが、代わりに 'Monad m => m(ma) - > ma'を試してみてください。なぜそのクエリが動作するのかについて –

+0

Whoops ...型コンストラクタは左を関連付けるものではありません... –

関連する問題