У меня есть функция, которая может выйти из строя, поэтому возвращаемое значение должно быть завершено в Maybe. Он использует другую функцию, которая также может потерпеть неудачу, и это также завернуто в Maybe. Проблема заключается в том, чтобы заставить типы работать в промежуточном вычислении, я должен «преждевременно» поднять функцию для работы в контексте Maybe. Это приводит к тому, что я получаю тип Maybe [Maybe Integer], когда я хочу, может быть, [Integer]. Эта функция является функцией exptDecipherString, функция, которая вызывает «преждевременный» подъем, является модульной инверсной функцией.Как избавиться от лишнего Может быть
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)
Я пробовал Hoogle, может быть, я не знаю, как его использовать. Я набрал «Monad m => m m a-> m a» или что-то в этом роде. Я все еще пытаюсь понять, как мыслить в типах :( –
@JoshInfiesto Ваш запрос почти прав! Вы только что забыли некоторые круглые скобки. Попробуйте 'Monad m => m (ma) -> ma' вместо этого, а затем подумайте о том, почему этот запрос работает. –
Упс ... Конструкторы типов ассоциируют левые, не так ли ... –