Haskell 如何摆脱一个额外的可能

Haskell 如何摆脱一个额外的可能,haskell,monads,functor,maybe,Haskell,Monads,Functor,Maybe,我有一个函数可能会失败,所以它返回的值需要包装在一个文件中。它使用了另一个可能也会失败的函数,该函数也包含在一个Maybe中。问题是,为了在中间计算中得到类型,我必须过早地提升一个函数,使其在上下文中工作。这导致我得到的类型可能是[Maybe Integer],而我想要的可能是[Integer]。所讨论的函数是exptDecipherString函数,强制提前提升的函数是modularInverse函数 import Data.Char import Control.Applicative im

我有一个函数可能会失败,所以它返回的值需要包装在一个文件中。它使用了另一个可能也会失败的函数,该函数也包含在一个Maybe中。问题是,为了在中间计算中得到类型,我必须过早地提升一个函数,使其在上下文中工作。这导致我得到的类型可能是[Maybe Integer],而我想要的可能是[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)

你通常应该尝试的第一件事是X如何变成Y。在这种情况下,它建议您使用join,它会将两个maybe折叠为一个

通过一些代码重组,Maybe monad也可以用来帮助您


当所有其他方法都失败时,使用函数或带有模式匹配的case语句推出您自己的解决方案。

您通常应该尝试的第一件事是X如何变成Y。在这种情况下,它建议您使用join,它会将两个maybe折叠为一个

通过一些代码重组,Maybe monad也可以用来帮助您


当所有其他方法都失败时,使用函数或带有模式匹配的case语句来推出您自己的解决方案。

我试过Hoogle,也许我对如何使用它很愚蠢。我输入了Monad m=>m m a->m a或者类似的东西。我仍在试图弄清楚如何在类型中思考:@JoshInfiesto您的查询几乎是正确的!你刚刚忘记了一些括号。试试Monad m=>m m a->m a,然后想想为什么该查询有效。@Josh Infiesto,是的,就像函数应用程序一样。值得指出的是,Hoogle足够聪明,对Maybe-Maybe-Integer->Maybe-Integer的查询将产生join::Monad m=>m m a->m a作为其第一个结果。我试过Hoogle,也许我对如何使用它很傻。我输入了Monad m=>m m a->m a或者类似的东西。我仍在试图弄清楚如何在类型中思考:@JoshInfiesto您的查询几乎是正确的!你刚刚忘记了一些括号。试试Monad m=>m m a->m a,然后想想为什么这个查询可以工作。@Josh Infiesto,是的,就像函数应用程序一样。值得指出的是,Hoogle足够聪明,对Maybe-Maybe-Integer->Maybe-Integer的查询将产生join::Monad m=>m m a->m a作为其第一个结果。