2012-04-02 82 views
1

我有一個函數可能會失敗,所以它返回的值需要包裝在一個Maybe中。它使用另一個也可能失敗的函數,這也包含在Maybe中。問題是,爲了讓類型在中間計算中得到解決,我必須「提前」提升函數以在Maybe語境中工作。這導致我得到一個類型Maybe [也許整數],當我想要的是可能[整數]。有問題的函數是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合併爲一個。

隨着一些代碼重組,Maybe monad也可以用來幫助你在這裏。

當所有其他問題都失敗時,將自己的解決方案與模式匹配使用函數或case語句。

+0

我試過Hoogle,也許我對如何使用它很無聊。我輸入了「Monad m => m m a-> m a」或類似的內容。我仍然試圖找出如何考慮類型:( – 2012-04-02 02:27:30

+3

@JoshInfiesto你的查詢幾乎是正確的!你忘記了一些括號,嘗試'Monad m => m(ma) - > ma',然後想想 – 2012-04-02 02:45:48

+0

哎呦......類型構造函數關聯了左邊,難道他們不是...... – 2012-04-02 02:54:14

相關問題