1

我是第一次玩 Haskell。

我创建了返回第一个足够精确结果的函数。它按预期工作,但我正在为此使用生成器。如何在此任务中更换生成器?

integrateWithPrecision precision =
    (take 1 $ preciseIntegrals precision) !! 0

preciseIntegrals :: Double -> [Double]
preciseIntegrals precision =
    [
        integrate (2 ^ power) pi | power <- [0..],
        enoughPowerForPrecision power precision
    ]
4

3 回答 3

3

你可以使用漂亮的until功能。这里是:

-- | @'until' p f@ yields the result of applying @f@ until @p@ holds.
until                   :: (a -> Bool) -> (a -> a) -> a -> a
until p f x | p x       =  x
            | otherwise =  until p f (f x)

所以,你可以这样写你的函数:

integrateWithPrecision precision = integrate (2 ^ pow) pi
  where
    pow = until done succ 0
    done pow = enoughPowerForPrecision pow precision

在您的情况下,您进行所有迭代,然后只计算一次结果。但until即使您需要在每一步计算结果也很有用 - 只需使用一个(iter, result)元组,然后只需result在末尾提取snd.

于 2013-09-29T20:51:33.377 回答
1

功能

\xs -> take 1 xs !! 0

叫做head

head []     = error "Cannot take head of empty list"
head (x:xs) = x

它的使用有点不安全,如图所示,如果您将一个空列表传递给它,它可能会引发错误,但在这种情况下,因为您可以确定您的列表是非空的,这很好。


此外,我们倾向于不在 Haskell 中将这些“生成器”称为“生成器”,因为它们不是特殊形式,而是惰性求值的简单结果。在这种情况下,preciseIntegrals称为“列表推导”,[0..]只不过是一个延迟生成的列表。

于 2013-09-29T18:26:35.560 回答
1

似乎你想检查越来越高的权力,直到你得到一个满足要求的权力。这就是你可以做的:首先你定义一个函数来获得足够的能量,然后你使用它来集成。

find获取满足条件的列表的第一个元素——比如足够的力量!然后我们需要 afromJust从中获取实际值。请注意,在您的代码中几乎总是fromJust有一个糟糕的想法。fromJust然而,在这种情况下,列表是无限的,所以在程序崩溃之前,我们就会遇到无限循环的麻烦。

enoughPower :: Double -> Int
enoughPower precision =
  fromJust $ find (flip enoughPowerForPrecision precision) [0..]

preciseIntegrals :: Double -> Double
preciseIntegrals precision = integrate (2^(enoughPower precision)) pi
于 2013-09-29T18:49:07.553 回答