2013-09-29 21 views
1

我第一次和Haskell一起玩。如果我只需要一个结果,我该如何更换发电机?

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

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

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

你想用什么替换它,为什么?我真的不明白你遇到的具体问题。 – kqr

+0

梯形法则整合。我需要第一个足够精确的结果。 – Devgru

回答

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 
+0

谢谢,'find'是非常有用的抽象,我可以理解为什么'fromJust'是个坏主意。 – Devgru

+0

您可以在'Data.List'中找到'find' – dg123

1

功能

\xs -> take 1 xs !! 0 

被称为head

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

它的使用是有点不安全,如它可如果你传递一个空列表抛出一个错误,但在这因为你可以确定你的列表是非空的,这很好。


而且,我们往往并不像他们不是一种特殊形式,但不是懒惰的评价的简单结果调用在Haskell这些“发电机”。在这种情况下,preciseIntegrals被称为“列表理解”,而[0..]不过是一个懒惰生成的列表。

+0

感谢“头”和“理解”。 Haskell有没有什么函数可以取代这个'理解'?我的主要经验是Java/JS/PHP,也许这就是为什么我尽可能避免使用列表的原因。 – Devgru

+1

@Devgru你可以用'map'和'filter'来代替你的理解,但是你不会从中获得任何额外的力量 - 这只是一种文体选择。目前还不清楚为什么你想要做这个替换。 – kqr

3

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

-- | @'until' p [email protected] yields the result of applying @[email protected] until @[email protected] 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)元组,然后在snd的末尾提取result即可。

相关问题