如果只需要一个结果,如何更换发电机?

时间:2013-09-29 18:14:12

标签: haskell generator

我第一次玩Haskell。

我创建的函数首先返回足够精确的结果。它按预期工作,但我正在使用发电机。如何在此任务中更换发电机?

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

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

3 个答案:

答案 0 :(得分:3)

您可以使用the beautiful until function。这是:

-- | @'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。< / p>

答案 1 :(得分:1)

功能

\xs -> take 1 xs !! 0

称为head

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

它的使用有些不安全,如图所示,如果你把它传递给空列表就会抛出一个错误,但在这种情况下你可以确定你的列表是非空的,这很好。


此外,我们倾向于不在Haskell中称这些“生成器”,因为它们不是一种特殊形式,而是懒惰评估的简单结果。在这种情况下,preciseIntegrals被称为“列表理解”,而[0..]只不过是一个懒惰的列表。

答案 2 :(得分:1)

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

find获取满足条件的列表的第一个元素 - 比如足够强大!然后我们需要fromJust来获取实际值。请注意,几乎所有fromJust都是可怕的想法。但是,在这种情况下,列表是无限的,所以在fromJust能够使程序崩溃之前很久就会遇到无限循环的麻烦。

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

preciseIntegrals :: Double -> Double
preciseIntegrals precision = integrate (2^(enoughPower precision)) pi