Haskell - Problems in the Mandelbrot drawer [closed] - haskell

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
So, as a beginner, I thought I would work on a horribly, awefully terrible version of the mandelbrot set project. In this pitiful case, the set is drawn with text (Shreik!) into a text file. Because I wanted some practice with some numerical coding, I have designed the worst complex number system in existance. I can't spot the problem in the code - the one that draws a band instead of a mandelbrot set. Here it is (don't look at it too long or you could die from over expossure to noob-ioactivity):
-- complex numbers, test for mandelbrot set
----------------- Complex Numbers
data C = Complex Float Float -- a + bi
deriving Show
data Mandelbrot = Possible -- if thought to be in mandelbrot set
| Not Integer -- this Integer is iterations before |z| > 2 in z=z^2+c
deriving Show
complexReal :: C -> Float
complexReal (Complex n _) = n
complexImaginary :: C -> Float
complexImaginary (Complex _ n) = n
modulus :: C -> Float
modulus (Complex n m) = sqrt ((n^2) + (m^2))
argument :: C -> Float --returns in radians
argument (Complex m n) | n < 0 && m < 0 = pi + (argument (Complex (0-m) (0-n)))
| m < 0 = (pi / 2) + (argument (Complex (0-m) n))
| n < 0 = ((3 * pi) / 2) + (argument (Complex m (0-n)))
| otherwise = atan (n / m)
multComplex :: C -> C -> C
multComplex (Complex m n) (Complex x y) = Complex ((m*x)-(n*y)) ((m*y)+(n*x))
addComplex :: C -> C -> C
addComplex (Complex m n) (Complex x y) = Complex (m + x) (m + y)
----------------- End Complex numbers
----------------- Mandelbrot
inMandelbrot :: C -> Mandelbrot
inMandelbrot c = inMandelbrotTest (Complex 0 0) c 0
--(z, c, i terations) with z=z^2+c, c is plotted on set map if z is bound
inMandelbrotTest :: C -> C -> Integer -> Mandelbrot
inMandelbrotTest z c i | (modulus z) > 2 = Not i -- too large
| i > 100 = Possible -- upper limit iterations
| otherwise = inMandelbrotTest (addComplex (multComplex z z) c) c (i+1)
possiblyInMandelbrot :: Mandelbrot -> Bool
possiblyInMandelbrot Possible = True
possiblyInMandelbrot _ = False
mandelbrotLine :: [C] -> String
mandelbrotLine [] = "\n"
mandelbrotLine (n:x) | possiblyInMandelbrot (inMandelbrot n) = "#" ++ mandelbrotLine x
mandelbrotLine (_:x) = " " ++ mandelbrotLine x
mandelbrotFeild :: [[C]] -> String
mandelbrotFeild [[]] = ""
mandelbrotFeild (n:x) = (mandelbrotLine n) ++ (mandelbrotFeild x)
-----------------End Mandelbrot
---------------- textual output
feildLine :: Float -> Float -> Float -> Float -> [C] -- start R, end R, i, increment x
feildLine s e i x | s > e = []
| otherwise = [(Complex s i)] ++ feildLine (s+x) e i x
feildGenerate :: Float -> Float -> Float -> Float -> Float -> [[C]] -- start R, end R, start i, end i, increment x
feildGenerate sr er si ei x | si > ei = [[]]
| otherwise = [(feildLine sr er si x)] ++ (feildGenerate sr er (si+x) ei x)
l1 :: String
l1 = mandelbrotFeild (feildGenerate (-3) 3 (-3) 3 0.05)
---------------- End textual output
main = do
writeFile "./mandelbrot.txt" (l1)
As you can see (or can't if you didn't look) there are some unused functions for my Complex numbers. Is there hope doctor?
Summary:
Why does this draw a band instead of the mandelbrot set?

Found your bug:
addComplex :: C -> C -> C
addComplex (Complex m n) (Complex x y) = Complex (m + x) (m + y)
It's really that simple. You have a trivial typo.
Some other suggestions:
Use Double rather than Float. For this example, it seems to give visibly more accurate results.
[x] ++ y is the same thing as x : y.
It is traditional to write x : xs rather than x : y. This makes it clear that one is a list element, the other is a list.
You can import Data.Complex to get complex-number arithmetic - but of course, you are writing this code for the purpose of learning, so that's fine.
If you define instance Num C where..., then you would be able to write z*z + c rather than addComplex (mulComplex z z) c. It's prettier to read - if you know how to write instances yet...
You can't spell "field". ;-)

Related

How does list generation with Fractionals work? [duplicate]

This question already has answers here:
Haskell ranges and floats
(2 answers)
Is floating point math broken?
(31 answers)
Closed 4 years ago.
If i want to generate a list with the input:
[3.1,5.1..8.1]
GHC 8.6.3 returns:
[3.1,5.1,7.1,9.099999999999998]
My problem here isn't the approximation of 9.1, but why the list made by GHC has one element more than the following solution.
In the documentation I found in GHC.Enum, that enumFromThenTo translates this to something similar to the following:
-- | Used in Haskell's translation of #[n,n'..m]# with
-- #[n,n'..m] = enumFromThenTo n n' m#, a possible implementation
-- being #enumFromThenTo n n' m = worker (f x) (c x) n m#,
-- #x = fromEnum n' - fromEnum n#, #c x = bool (>=) (<=) (x > 0)#
-- #f n y
-- | n > 0 = f (n - 1) (succ y)
-- | n < 0 = f (n + 1) (pred y)
-- | otherwise = y# and
-- #worker s c v m
-- | c v m = v : worker s c (s v) m
-- | otherwise = []#
So the following code:
import Data.Bool
eftt n s m = worker (f x) (c x) n m
where x = (fromEnum s) - (fromEnum n)
c x = bool (>=) (<=) (x > 0)
f n y
| n > 0 = f (n-1) (succ y)
| n < 0 = f (n+1) (pred y)
| otherwise = y
worker s c v m
| c v m = v: worker s c (s v) m
| otherwise = []
On the same input as before, this however returns this list:
[3.1,5.1,7.1]
The real implementation defined in GHC.Enum is the following:
enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]
But there is no instantiation of Enum Double or Enum Float in GHC.Enum
So when I tried to reproduce this with the following code:
import Prelude(putStrLn,show)
import GHC.Enum(toEnum,fromEnum,Enum,enumFromThenTo)
import GHC.Base(map)
main = putStrLn (show (_enumFromThenTo 3.1 5.1 8.1))
_enumFromThenTo :: (Enum a) => a -> a -> a -> [a]
_enumFromThenTo x1 x2 y = map toEnum [fromEnum x1, fromEnum x2 .. fromEnum y]
I compiled with:
$ ghc -package ghc -package base <file.hs>
The result was again:
[3.0,5.0,7.0]
What is happening here, such that the output becomes:
[3.1,5.1,7.1,9.099999999999998]
?
Well, this is instance Enum Double
instance Enum Double where
enumFromThenTo = numericEnumThenFromTo
The implementation is here
numericEnumFromThenTo :: (Ord a, Fractional a) => a -> a -> a -> [a]
numericEnumFromThenTo e1 e2 e3
= takeWhile predicate (numericEnumFromThen e1 e2)
where
mid = (e2 - e1) / 2
predicate | e2 >= e1 = (<= e3 + mid)
| otherwise = (>= e3 + mid)
More important than the implementation is the note above it:
-- These 'numeric' enumerations come straight from the Report
Which refers to this passage in the (2010) Report:
For Float and Double, the semantics of the enumFrom family is given by the rules for Int above, except that the list terminates when the elements become greater than e3 + i∕2 for positive increment i, or when they become less than e3 + i∕2 for negative i.
(Where e3 refers to the upper bound, and i the increment.)
The comment you found on Enum and the implementation in class Enum are both irrelevant. The comment is just example code detailing how an instance might be implemented, and the implementation given is inside a class, and thus may be overridden with anything.

How do I avoid stackoverflow error in Haskell

I want to make this Function:
calling customPower 2 2
would give back 2^2 + 2^1 + 1
calling customPower 3 3
would give back 3^3 + 3^2 + 3^1 + 1
Here is my code:
customPower :: Int -> Int -> Int
customPower x y
| y == 0 = 1
| y > 0 = (x^(y)) + (customPower x y-1)
It gives me stack overflow exception and I can't find where is the error. Everything seems fine.
The operators have lower precedence than function calls, this means that your recursive call:
... + (customPower x y-1)
is interpreted as:
... + ((customPower x y)-1)
so you keep calling with the same parameters, therefore the recursion can never end.
We can fix this by adding brackets for y-1:
customPower :: Int -> Int -> Int
customPower x y
| y > 0 = x^y + customPower x (y-1)
| otherwise = 1
With this modifications, we do not get stuck in an infinite loop:
Prelude> customPower 5 3
156
We can rewrite the above by making use of sum :: Num a => [a] -> a and map :: (a -> b) -> [a] -> [b] to implement this with a one-liner:
customPower :: (Num a, Integral b) => a -> b -> a
customPower x y = sum (map (x^) [0..y])
or we can use iterate :: (a -> a) -> a -> [a]:
customPower :: (Num a, Integral b) => a -> b -> a
customPower x y = sum (take (y+1) (iterate (x*) 1))
Due to Haskell's laziness, the above attempts will likely still result in a call stack that scales linear with the value of y: the functions are, like #dfeuer says, not tail recursive functions, we can however work with an accumulator here:
customPower :: Int -> Int -> Int
customPower x = go 1
where go a y | y > 1 = a
| otherwise = seq a (go (a+x^y) (y-1))
since the above sum is equal to a simple formula, we can even calculate the value in O(y log x):
y
.———— y+1
╲ i x - 1
╱ x = ————————
*———— x - 1
i=0
So we can calculate the value with:
customPower :: (Integral a, Integral b) => a -> b -> a
customPower x y = div (x^(y+1) - 1) (x - 1)
This will usually work faster, although in a rare case where the result times x -1 is larger than the maximum representable number of the type a, this will result in overflow and will return the wrong number.

strange haskell parse error

So I've only a little experience with Haskell and I've been working on the below program to implement a search to find maxima in a function, yet I've been receiving an odd error. When I compile it says:
MaximaSearch.hs:26:1:
parse error (possibly incorrect indentation or mismatched brackets)
That's the line that says "main = do" so I think it's some sort of trailing error from my indentation in the code preceding it but I can't spot any mistakes...
Here's the code:
module Main where
g :: Float -> Float
--your function here
g x = cos(x^2)
--goldenSectionSearch
goldenSS :: (Float -> Float) -> Float -> Float -> Float -> Float -> Float
goldenSS f a b c tau
| (c-a) < tau * (abs b + abs x) = (c+a)/2
|f x > f b = let
t1|(c - b) > (b-a) = goldenSS f b x c tau
|otherwise = goldenSS f a x b tau
in t1
|otherwise = let
t2|(c-b) > (b-a) = goldenSS f a b x tau
|otherwise = goldenSS f x b c tau
in t2
where
let x
| (c-b) > (b-a) = b + resphi*(c-b)
|otherwise = b - resphi*(b-a)
where resphi = 2 - phi where phi = (1+ sqrt 5)/2
in x
--main
main = do
print x
print (g x)
where
x = goldenSS g a ((a+b)/2) b tau
where
a = 2
b = 3
tau = 0.001
any ideas?
The reason you're getting the parse error stems from the non-idiomatic usage of let and where bindings in your code.
Haskell allows multiple syntactic structures for temporary bindings and pattern matching, but you're combining them in a rather strange and messy manner.
To learn how to write the code cleaner and in a manner more usual for Haskell, I'd recommend looking up existing haskell libraries and programs (for example on hackage) to get a feel for how let and where bindings usually work. In general I find that for pure functions I almost exclusively use where (as opposed to let), but certain things are stylistic.
As for this code, I modified it a bit to use where bindings instead of let, and it compiles and runs for me now. Even if you have to tweak it a bit to get it to compile for you, this overall structure is cleaner and less likely to give you parse errors:
module Main where
g :: Float -> Float
g x = cos(x^2)
goldenSS :: (Float -> Float) -> Float -> Float -> Float -> Float -> Float
goldenSS f a b c tau
|(c-a) < tau * (abs b + abs x) = (c+a)/2
|f x > f b = t1
|otherwise = t2
where x | (c-b) > (b-a) = b + resphi*(c-b)
|otherwise = b - resphi*(b-a)
resphi = 2 - phi
phi = (1+ sqrt 5)/2
t1 |(c - b) > (b-a) = goldenSS f b x c tau
|otherwise = goldenSS f a x b tau
t2 |(c-b) > (b-a) = goldenSS f a b x tau
|otherwise = goldenSS f x b c tau
main =
do
print x
print (g x)
where x = goldenSS g a ((a+b)/2) b tau
a = 2
b = 3
tau = 0.001

Can't properly understand lambdas in Haskell

I have following code, implmenting inverse function calculation, basing on this formulas:
derivation :: (Fractional a) => (a -> a) -> (a -> a)
derivation f = \ x -> ( ( f (x + dx) - f (x) ) / dx ) where dx = 0.1
evalA k f
| k == 0 = \x -> x
| otherwise = \x -> (derivation (evalA (k-1) f) x) / (derivation f x)
inverseFun f x =
let
x0 = 3.0
eps = 0.001
iter k prev sum =
let
elemA = evalA k f x0
elemB = prev * (x - (f x0)) / (if k == 0 then 1 else k)
newItem = elemA * elemB
in
if abs (newItem) < eps
then sum
else iter (k + 1) elemB (sum + newItem)
in
iter 0 1.0 0.0
f1 = \x -> 1.0 * x * x
main = do
print $ inverseFun f1 2.5
I need to optimise it by moving evalA inside the inverseFun and store previous step calculation A'n/F' to reuse it on the next iteration, if possible. As far as I understand, each time evalA returns some sort of function and x applies afterwards, right before declaring elemA.
How can I convert my evalA or rewrite it to store previous results (by passing these results in iter, obviously)?
Don't mind if this calculations are not too precise, it requires good x0 and eps choice. My main question is in lambda conversion.
If you change your definition of inverseFun such that the (if k == 0 then 1 else k) is instead fromIntegral (if k == 0 then 1 :: Int else k), then you can provide type signatures to all of your functions:
derivation :: (Fractional a) => (a -> a) -> a -> a
evalA :: (Fractional a) => Int -> (a -> a) -> a -> a
inverseFun :: (Fractional a, Ord a) => (a -> a) -> a -> a
f1 :: (Fractional a) => a -> a
Which certainly helps out.
This is actually important for my solution to your problem, since we need k to be an Int, and you've used it as a Fractional a => a. The fromIntegral fixes that, but it needs to know that it's an Int, so I just added the inline type signature to help the compiler along.
Since your function only depends on the previous single value, you can use our handy friend from Prelude, iterate :: (a -> a) -> a -> [a]. This applies a function over and over again, producing an infinite list of values. We can then index it at any point to get the desired result (this is why having k an Int is important!).
Our function will look like
evalA :: Fractional a => Int -> (a -> a) -> a -> a
evalA k f = iterate go id !! k
where
go = ???
Here id is the same as your base case of \x -> x, just shorter and with more optimization rules. It serves as the initial value for generating this list. To implement go, the actual computation, we need it to accept the previous result as its argument:
where
go prev = \x -> derivation prev x / derivation f x
But this is considered "poor style" by hlint, and so it is suggested to convert this to the form
where
go prev x = derivation prev x / derivation f x
And that's it! I tested it and got the exact same result for your example input. The full code can be viewed here.

Type declaration for number division

I tried all possible type declarations but I can't make this code even compile. The trick is in handling types for division. I tried Num a, Fractional a, Float a etc.
cube x = x * x * x
sum' term a next b =
if a > b
then 0
else term a + sum' term (next a) next b
integral f a b n = (h / 3) * (sum' term 0 succ n) where
h = (b - a) / n
y k = f $ a + (k * h)
term k
| k == 0 || k == n = y k
| odd k = 4 * y k
| even k = 2 * y k
main = do
print $ integral cube 0 1 100 -- 0.25
print $ (\x -> 3 * x * x) 1 3 100 -- 26
I isolated problem by deleting (/) function. This code compiles without any type declaration at all:
cube x = x * x * x
sum' term a next b =
if a > b
then 0
else term a + sum' term (next a) next b
integral f a b n = (sum' term 0 succ n) where
h = (b - a)
y k = f $ a + (k * h)
term k
| k == 0 || k == n = y k
| odd k = 4 * y k
| even k = 2 * y k
main = do
print $ integral cube 0 1 100
Another question is how to debug cases like this? Haskell's error messages doesn't help much, it's kind of hard to understand something like The type variable a0 is ambiguous or Could not deduce (a1 ~ a).
P. S. It's ex. 1.29 from SICP.
Update
Final answer is:
cube :: Num a => a -> a
cube x = x * x * x
sum' :: (Int -> Double) -> Int -> (Int -> Int) -> Int -> Double
sum' term a next b =
if a > b
then 0
else term a + sum' term (next a) next b
integral :: (Double -> Double) -> Double -> Double -> Int -> Double
integral f a b n = (h / 3) * sum' term 0 (+1) n where
h = (b - a) / n' where n' = fromIntegral n
y k = f $ a + (k * h)
term k
| k == 0 || k == n = y k'
| odd k = 4 * y k'
| even k = 2 * y k'
where k' = fromIntegral k
main = do
print $ integral cube 0 1 100 -- 0.25
print $ integral cube 0 1 1000 -- 0.25
print $ integral (\x -> 3 * x * x) 1 3 100 -- 26
/ is only used for types that are instances of Fractional, for Integral types use quot. You can use quot as an infix operator using backticks:
h = (b - a) `quot` n
The types of the two are
(/) :: Fractional a => a -> a -> a
quot :: Integral a => a -> a -> a
There are no types that are instances of both Fractional and Integral, which is why none of the type signatures would work. Unfortunately GHC doesn't know that it's impossible for a type to be an instance of both classes, so the error messages are not very intuitive. You get used to the style of GHC error messages though, and the detail they give helps a lot.
Also, as was suggested in the comments, I completely agree that all top level definitions should be given type signatures (including main). It makes error messages a lot easier to read.
Edit: Based on the comments below, it looks like what you want is something more like this (type signature-wise)
cube :: Num a => a -> a
sum' :: (Int -> Double) -> Int -> (Int -> Int) -> Int -> Double
integral :: (Double -> Double) -> Double -> Double -> Int -> Double
You will need to use fromIntegral to convert from Int to Double in h and in k. The type errors should be at least a bit more readable with these type signatures though.

Resources