此代码返回从2开始的Integer的第一个因子,如果它是素数则不返回任何内容。
示例:firstFactorOf 24返回"只是2"
示例:firstFactorOf 11返回" Nothing"
我的问题是,如何返回值2而不是"只是2"如果有一个因子,或者如果没有因子则返回值x。
firstFactorOf x
| m == Nothing = m
| otherwise = m
where m =(find p [2..x-1])
p y = mod x y == 0
//RETURNS:
ghci> firstFactorOf 24
Just 2
ghci> firstFactorOf 11
Nothing
答案 0 :(得分:5)
Haskell是静态类型的,这意味着您可以定义函数Maybe a -> a
,但问题是如何处理Nothing
情况。
Haskell有两个在这里有用的功能:fromMaybe
和fromJust
:
fromMaybe :: a -> Maybe a -> a
fromJust :: Maybe a -> a
fromJust
只是假设您将始终提供Just x
,并返回x
,在另一种情况下,它会抛出异常。
fromMaybe
需要两个参数,第一个 - a
是"默认情况"在Nothing
的情况下应该返回的值。接下来给它Maybe a
,如果它是Just x
,则返回x
。在另一种情况下(Nothing
),如前所述,返回默认值。
在评论中,您说如果不存在此类因素,则应返回x
。所以我建议你定义一个新函数:
firstFactorOfJust :: Integral a => a -> a
firstFactorOfJust x = fromMaybe x $ firstFactorOf x
因此,此功能firstFactorOfJust
会调用您的firstFactorOf
函数,如果结果为Nothing
,则会返回x
。在另一种情况下,将返回firstFactorOf
的结果(但仅返回Integral
部分,而不是Just ...
部分。
编辑(简化)
基于你自己的想要简化一些事情的答案,我有一个想法,你可以简化一点:
firstFactorOf x | Just z <- find ((0 ==) . mod x) [2..x-1] = z
| otherwise = x
既然我们都是优化的粉丝,那么你可以在sqrt(x)
次迭代之后停止(在素数检查中一个众所周知的优化):
isqrt :: Int -> Int
isqrt = floor . sqrt . fromIntegral
firstFactorOf x | Just z <- find ((0 ==) . mod x) [2..isqrt x] = z
| otherwise = x
简化问题
出于某种原因,你的问题中存在一些特别复杂的方面:
firstFactorOf x
| m == Nothing = m
| otherwise = m
where m =(find p [2..x-1])
p y = mod x y == 0
为什么使用警卫来区分两个产生完全相同输出的情况?您可以将其折叠为:
firstFactorOf x = m
where m = (find p [2..x-1])
p y = mod x y == 0
甚至更进一步:
firstFactorOf x = find p [2..x-1]
where p y = mod x y == 0
答案 1 :(得分:2)
如果您希望它返回x
或x
的第一个因子,那么这应该有效:
firstFactorOf x =
let
p y = mod x y == 0
m = (find p [2..x-1])
in
fromMaybe x m
答案 2 :(得分:-1)
import Data.List
import Data.Maybe
firstFactorOf x
| m == Nothing = x
| otherwise = fromJust m
where m =(find p [2..x-1])
p y = mod x y == 0
这就是我追求的目标。不知道为什么你们这么复杂。