2

我有这个在 TI Basic 中编写的复杂迭代程序,用于对复数执行基本迭代,然后给出结果的大小:

INPUT “SEED?”, C
INPUT “ITERATIONS?”, N
C→Z
For (I,1,N)
Z^2 + C → Z
DISP Z
DISP “MAGNITUDE”, sqrt ((real(Z)^2 + imag(Z)^2))
PAUSE
END

我想做的是制作一个 Haskell 版本,让我的老师在作业中惊叹不已。我仍然只是在学习并做到了这一点:

fractal ::(RealFloat a) =>
          (Complex a) -> (Integer a) -> [Complex a]
fractal c n | n == a = z : fractal (z^2 + c)
   | otherwise = error "Finished"

我不知道该怎么做是如何让它只迭代n次数,所以我想让它计数a,然后比较它n是否已经完成。

我该怎么办?

4

3 回答 3

4

Newacct 的回答表明了这一点:

fractal c n = take n $ iterate (\z -> z^2 + c) c

Iterate生成重复应用程序的无限列表。前任:

iterate (2*) 1 == [1, 2, 4, 8, 16, 32, ...]

关于 IO,您必须进行一些单子计算。

import Data.Complex
import Control.Monad

fractal c n = take n $ iterate (\z -> z^2 + c) c

main :: IO ()
main = do
    -- Print and read (you could even omit the type signatures here)
    putStr "Seed: "
    c <- readLn :: IO (Complex Double)

    putStr "Number of iterations: "
    n <- readLn :: IO Int

    -- Working with each element the result list
    forM_ (fractal c n) $ \current -> do
        putStrLn $ show current
        putStrLn $ "Magnitude: " ++ (show $ magnitude current)

由于 Complex 默认情况下可与字符串相互转换,因此您可以使用readLn从控制台读取它们(格式为Re :+ Im)。

编辑:只是为了好玩,可以对单子语法和类型签名进行脱糖,这会将整个程序压缩为:

main = 
    (putStr "Seed: ") >> readLn >>= \c -> 
    (putStr "Number of iterations: ") >> readLn >>= \n -> 
    forM_ (take n $ iterate (\z -> z^2 + c) c) $ \current ->
    putStrLn $ show current ++ "\nMagnitude: " ++ (show $ magnitude current)

编辑#2:一些与绘图和 Mandelbrot 集相关的链接。

于 2009-09-12T11:44:38.580 回答
3

好吧,您总是可以生成重复应用程序的无限结果列表,n并使用take. 该iterate函数对于生成重复应用的结果的无限列表很有用。

于 2009-09-12T07:16:28.163 回答
2

如果您想要一个值列表:

fractalList c n = fractalListHelper c c n
                  where 
                     fractalListHelper z c 0 = []
                     fractalListHelper z c n = z : fractalListHelper (z^2 + c) c (n-1)

如果你只关心最后的结果:

fractal c n = fractalHelper c c n
                  where
                    fractalHelper z c 0 = z
                    fractalHelper z c n = fractalHelper (z^2 + c) c (n-1)

基本上,在这两种情况下,您都需要一个辅助函数来计算和累积。现在我确信有更好/更简洁的方法来做到这一点,但我自己几乎是一个 Haskell 新手。

编辑:只是为了踢,一个折叠单线:

fractalFold c n = foldr (\c z -> z^2 + c) c (take n (repeat c)) 

(虽然, (take n (repeat c)) 这件事似乎有点不必要,但必须有更好的方法)

于 2009-09-12T08:02:52.793 回答