Just Int to Int

时间:2017-01-29 20:41:57

标签: haskell find

此代码返回从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

3 个答案:

答案 0 :(得分:5)

Haskell是静态类型的,这意味着您可以定义函数Maybe a -> a,但问题是如何处理Nothing情况。

Haskell有两个在这里有用的功能:fromMaybefromJust

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)

如果您希望它返回xx的第一个因子,那么这应该有效:

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

这就是我追求的目标。不知道为什么你们这么复杂。