Beginner to Haskell type system : "Haskell non-type variable argument in constraint" Error - haskell

In an attempt to dip my toes in functional programming, I'm attempting to pick up Haskell and running into some mental issues with the type system.
Running the following code gives proper output (e.g. generates coordinates for a circle wrapped around a cylinder of radius R at angle theta):
coilGeneration_AngleTest housingRadius coilWidth coilDepth numEle zoffset centralAngle
= [ (x',y',z)
| theta <- [0,2*pi/(numEle-1)..2*pi]
, let x = housingRadius * cos(coilWidth*cos(theta)/housingRadius)
, let y = housingRadius * sin(coilWidth*cos(theta)/housingRadius)
, let z = coilDepth * sin(theta)+zoffset
, let x' = x * cos(centralAngle) - y * sin(centralAngle)
, let y' = x * sin(centralAngle) + y * cos(centralAngle)
]
Sample coilGeneration_AngleTest function output
However, attempting to generalize this into a function that generates an arbitrary NxM array of circles with varying overlaps in the polar and z-directions by running:
coilArrayGeneration_Test r nE width depth n m mu gam
= [ (x',y',z',i,j)
| theta <- [0,2*pi/(nE-1)..2*pi]
, i <- [1..n]
, j <- [1..m]
, let a = width/2
, let b = depth/2
, let x = r * cos(a*cos(theta)/r)
, let y = r * sin(a*cos(theta)/r)
, let z = b * sin(theta)
, let phi = (2*i-1-n)((a-mu)/r)
, let zo = (2*j-1-m)(b-gam)
, let x' = x * cos(phi) - y * sin(phi)
, let y' = x * sin(phi) + y * cos(phi)
, let z' = z + zo
]
gives the following error:
Build profile: -w ghc-9.2.5 -O1
In order, the following will be built (use -v for more details):
- Haskell-0.1.0.0 (exe:Haskell) (file app/Main.hs changed)
Preprocessing executable 'Haskell' for Haskell-0.1.0.0..
Building executable 'Haskell' for Haskell-0.1.0.0..
[1 of 1] Compiling Main ( app/Main.hs, /Users/zack/Desktop/Udemy/Haskell/dist-newstyle/build/aarch64-osx/ghc-9.2.5/Haskell-0.1.0.0/x/Haskell/build/Haskell/Haskell-tmp/Main.o )
app/Main.hs:66:1: error:
• Non type-variable argument in the constraint: Num (c -> c)
(Use FlexibleContexts to permit this)
• When checking the inferred type
coilArrayGeneration_Test :: forall {c}.
(Floating c, Num (c -> c), Enum c, Enum (c -> c)) =>
c
-> c
-> c
-> c
-> (c -> c)
-> (c -> c)
-> c
-> c
-> [(c, c, c, c -> c, c -> c)]
|
66 | coilArrayGeneration_Test r nE width depth n m mu gam = [(x',y',z',i,j)|theta <- [0,2*pi/(nE-1)..2*pi],....
Failure Output
After googling for a while, it seemed that my function had an improper type implied by the compiler but I unfortunately don't understand the idea Haskell Type Definition well enough to fix it. I attempted to define the types the way I see them, namely:
r -> Double
nE -> Int
width -> Double
depth -> Double
n -> Int
m -> Int
mu -> Double
gam -> Double
x' -> Double
y' -> Double
z' -> Double
I -> Int
j -> Int
Getting:
coilArrayGeneration_Test :: (Floating a, Integral b) => a -> b -> a -> a -> b -> b -> a -> a -> [(a,a,a,b,b)]
coilArrayGeneration_Test r nE width depth n m mu gam
= [ (x',y',z',i,j)
| theta <- [0,2*pi/(nE-1)..2*pi]
, i <- [1..n]
, j <- [1..m]
, let a = width/2
, let b = depth/2
, let x = r * cos(a*cos(theta)/r)
, let y = r * sin(a*cos(theta)/r)
, let z = b * sin(theta)
, let phi = (2*i-1-n)((a-mu)/r)
, let zo = (2*j-1-m)(b-gam)
, let x' = x * cos(phi) - y * sin(phi)
, let y' = x * sin(phi) + y * cos(phi)
, let z' = z + zo
]
But this threw a whole host of errors:
Errors after Type Declaration
Which clearly means I don't know what I'm doing and mucked up the type declarations somehow.
Can anyone steer me the right way?

When you see a compiler error involving something like Num (c -> c), it never has anything to do with -XFlexibleContexts or with incorrect inferred types. It simply means you attempted to use something as a function which is not a function.
“Use as a function” entails simply that you have some expression of the form f x, where f and x can be arbitrary subexpressions. This includes in particular also expressions like (1+2)(3+4), which is the same as
let f = 1 + 2
x = 3 + 4
in f x
Presumably you meant to express multiplication by the juxtaposition. Well, use the multiplication operator then! I.e. (1+2)*(3+4).
Your code has also another problem: you trying to use the index variables in real-valued expression. Unlike the missing multiplication operators, this is fairly sensible, but Haskell doesn't allow this either. You need to explicitly wrap the integrals in fromIntegral.
coilArrayGeneration_Test r nE width depth n m μ γ
= [ (x',y',z',i,j)
| ϑ <- [0, 2*pi/fromIntegral(nE-1) .. 2*pi]
, i <- [1..n]
, j <- [1..m]
, let a = width/2
b = depth/2
x = r * cos(a*cos ϑ/r)
y = r * sin(a*cos ϑ/r)
z = b * sin ϑ
φ = fromIntegral(2*i-1-n) * ((a-μ)/r)
z₀ = fromIntegral(2*j-1-m) * (b-γ)
x' = x * cos φ - y * sin φ
y' = x * sin φ + y * cos φ
z' = z + z₀
]
I would strongly recommend you refactor this a bit, both code and types. 5-tuples are very obscure, you should at least wrap x,y,z in a suitable vector type.

Related

How to create a function that generates an infinite list of an integer-sequence that is defined recursively with two initial numbers X_0 and X_1

Let's say I have the recursive definition for the following sequence of integers: a_0 = 5, a_n = 2a_0+3 -> 5,13,29,61,125...
I want to use the iterate function in Haskell to generate an infinite list of this sequence. To do that I could write the following code:
intSequence :: Integer -> Integer -> [Integer]
intSequence a0 m = iterate nextNum a0
where nextNum a = 2*a + m
ghci> let an = intSequence 5 3
ghci> take 5 a
[5,13,29,61,125]
Now let's say I instead have the following:
X_n = X_n-1 * m_1 + X_n-2 * m_2 + a
Now I want to create a function called in the following way:
intSequence x0 x1 m1 m2 a
that returns an infinite list of a sequence that adheres to the rules of the definition above.
For example: For parameters X0=1, X1=2, m1=2, m2=0, a=0 we get Xn=X_n-1 * 2 + X_n-2 * 0 + 0 = X_n-1 * 2 which gives us [1,2,4,8,16,...]
Another example: For parameters X0=0, X1=1, m1=1, m2=1, a=0 we get the Fibonacci-sequence X_n = X_n-1 * 1 + X_n-2 * 1 + 0 = X_n-1 + X_n-2 which gives us [0,1,1,2,3,5,8,...]
How can I implement this intSequence function using iterate?
I tried the following which does not work as intended:
intSequence :: Integer -> Integer -> Integer -> Integer -> Integer -> [Integer]
intSequence x0 x1 m1 m2 a = x0:x1:iterate (nextNum x0) x1
where
nextNum x0' x1' = x1'*m1 + x0'*m2 + a
ghci> a = intSequence 0 1 1 1 0
ghci> take 10 a
[0,1,1,1,1,1,1,1,1,1]
Which obviously is incorrect and logically so as I never change what x0 and x1 are. I think I need to use recursion somehow but I just can't figure out how. Should I maybe not use iterate at all?
This is much easier to do with recursion:
-- helper function for recursion
intSequence' :: (Integral a) => (a, a) -> a -> a -> a -> [a]
-- p2 is X_n-2 and p1 is X_n-1
intSequence' (p2, p1) m1 m2 a =
-- recurse using X_n-1 as new X_n-2 and current term as new X_n-1
cur:intSequence' (p1, cur) m1 m2 a
-- calculate the current term in the sequence
where cur = p1 * m1 + p2 * m2 + a
-- set previous terms correctly and prepend them to the sequence
intSequence :: (Integral a) => a -> a -> a -> a -> a -> [a]
intSequence x0 x1 m1 m2 a = x0:x1:intSequence' (x0, x1) m1 m2 a

Weird behavior of (^) in Haskell

Why does GHCi give incorrect answer below?
GHCi
λ> ((-20.24373193905347)^12)^2 - ((-20.24373193905347)^24)
4.503599627370496e15
Python3
>>> ((-20.24373193905347)**12)**2 - ((-20.24373193905347)**24)
0.0
UPDATE
I would implement Haskell's (^) function as follows.
powerXY :: Double -> Int -> Double
powerXY x 0 = 1
powerXY x y
| y < 0 = powerXY (1/x) (-y)
| otherwise =
let z = powerXY x (y `div` 2)
in if odd y then z*z*x else z*z
main = do
let x = -20.24373193905347
print $ powerXY (powerXY x 12) 2 - powerXY x 24 -- 0
print $ ((x^12)^2) - (x ^ 24) -- 4.503599627370496e15
Although my version doesn't appear any more correct than the one provided below by #WillemVanOnsem, it strangely gives the correct answer for this particular case at least.
Python is similar.
def pw(x, y):
if y < 0:
return pw(1/x, -y)
if y == 0:
return 1
z = pw(x, y//2)
if y % 2 == 1:
return z*z*x
else:
return z*z
# prints 0.0
print(pw(pw(-20.24373193905347, 12), 2) - pw(-20.24373193905347, 24))
Short answer: there is a difference between (^) :: (Num a, Integral b) => a -> b -> a and (**) :: Floating a => a -> a -> a.
The (^) function works only on integral exponents. It will normally make use of an iterative algorithm that will each time check if the power is divisible by two, and divide the power by two (and if non-divisible multiply the result with x). This thus means that for 12, it will perform a total of six multiplications. If a multiplication has a certain rounding-off error, that error can "explode". As we can see in the source code, the (^) function is implemented as:
(^) :: (Num a, Integral b) => a -> b -> a
x0 ^ y0 | y0 < 0 = errorWithoutStackTrace "Negative exponent"
| y0 == 0 = 1
| otherwise = f x0 y0
where -- f : x0 ^ y0 = x ^ y
f x y | even y = f (x * x) (y `quot` 2)
| y == 1 = x
| otherwise = g (x * x) (y `quot` 2) x -- See Note [Half of y - 1]
-- g : x0 ^ y0 = (x ^ y) * z
g x y z | even y = g (x * x) (y `quot` 2) z
| y == 1 = x * z
| otherwise = g (x * x) (y `quot` 2) (x * z) -- See Note [Half of y - 1]
The (**) function is, at least for Floats and Doubles implemented to work on the floating point unit. Indeed, if we take a look at the implementation of (**), we see:
instance Floating Float where
-- …
(**) x y = powerFloat x y
-- …
This thus redirect to the powerFloat# :: Float# -> Float# -> Float# function, which will, normally be linked to the corresponding FPU operation(s) by the compiler.
If we use (**) instead, we obtain zero as well for a 64-bit floating point unit:
Prelude> (a**12)**2 - a**24
0.0
We can for example implement the iterative algorithm in Python:
def pw(x0, y0):
if y0 < 0:
raise Error()
if y0 == 0:
return 1
return f(x0, y0)
def f(x, y):
if (y % 2 == 0):
return f(x*x, y//2)
if y == 1:
return x
return g(x*x, y // 2, x)
def g(x, y, z):
if (y % 2 == 0):
return g(x*x, y//2, z)
if y == 1:
return x*z
return g(x*x, y//2, x*z)
If we then perform the same operation, I get locally:
>>> pw(pw(-20.24373193905347, 12), 2) - pw(-20.24373193905347, 24)
4503599627370496.0
Which is the same value as what we get for (^) in GHCi.

Assigning special cases when certain variables have certain values?

for my functional programming homework I am instructed to write a function that gives back the real solutions of a quadratic equation in a list, I used the discriminant to find them out.
So, my code looks something like this:
quadSols::Double->Double->Double->[Double]
quadSols a b c = [x1,x2]
where
x1 = (-b - sqrt d) / (2 * a)
x2 = (-b + sqrt d) / (2 * a)
d = (b * b) - 4 * a * c
Now, the problem is in the case a = 0, for which the solution would be simply x = -c / b.
I tried something like this, it sounds completely wrong but I don't really know what to do.
if a == 0 then quadSols a b c = [x]
and then added to the "where" part:
x = -c / b
when trying to load it with ghci I get:
parse error on input ‘=’
Failed, modules loaded: none.
Can anyone provide me with some guidance?
You can simply pattern match for the case where a == 0:
quadSols :: Double -> Double-> Double-> [Double]
quadSols 0 b c = [x]
where x = -c / b
quadSols a b c = [x1,x2]
where
x1 = (-b - sqrt d) / (2 * a)
x2 = (-b + sqrt d) / (2 * a)
d = (b * b) - 4 * a * c
Note that you must include the first case before the second, since cases are matched in the order they are declared.
You can add another equation to quadSols:
quadSols 0 b c = [x]
where
x = (-c) / b
quadSols a b c = [x1,x2]
where
…
Or use a guard:
quadSols a b c
| a == 0 = [x]
| otherwise = [x1,x2]
where
x = (-c) / b
…
Due to laziness, the definitions in the where clause won’t be evaluated unless necessary to produce a result.

How do I optimize numerical integration performance in Haskell (with example)

How do I optimize numerical integration routine (comparing to C)?
What has been done to the moment:
I replaced lists with unboxed vectors (obvious).
I applied profiling techniques described in the book "Read World Haskell" http://book.realworldhaskell.org/read/profiling-and-optimization.html.
I have inlined some trivial functions and inserted a lot of bangs everywhere.
That gave about 10x speedup.
I refactored the code (i.e. extracted iterator function). That gave 3x speedup.
I tried to replace polymorphic signatures with Floats
as in the answer to this question
Optimizing numerical array performance in Haskell.
That gave almost 2x speedup.
I compile like this
cabal exec ghc -- Simul.hs -O2 -fforce-recomp -fllvm -Wall
UPDATE As suggested by cchalmers, type Sample = (F, F) was replaced with
data Sample = Sample {-# UNPACK #-} !F {-# UNPACK #-} !F
The performance now is almost as good as C code. Can we do better?
{-# LANGUAGE BangPatterns #-}
module Main
where
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as UM
import qualified Control.Monad.Primitive as PrimitiveM
import Dynamics.Nonlin ( birefrP )
type F = Float
type Delay = U.Vector F
type Input = U.Vector F
-- Sample can be a vector of any length (x, y, z, ...)
data Sample = Sample {-# UNPACK #-} !F {-# UNPACK #-} !F
-- Pair is used to define exactly a pair of values
data Pair = Pair {-# UNPACK #-} !F {-# UNPACK #-} !F
type ParametrizedDelayFunction = (Sample, F) -> Sample
getX :: Sample -> F
getX (Sample a _) = a
{-# INLINE getX #-}
toDelay :: [F] -> Delay
toDelay = U.fromList
stepsPerNode :: Int
stepsPerNode = 40 -- Number of integration steps per node
infixl 6 ..+..
(..+..) :: Sample -> Sample -> Sample
(..+..) (Sample x1 y1) (Sample x2 y2) = Sample (x1 + x2) (y1 + y2)
{-# INLINE (..+..) #-}
infixl 7 .*..
(.*..) :: F -> Sample -> Sample
(.*..) c (Sample x2 y2) = Sample (c * x2) (c * y2)
{-# INLINE (.*..) #-}
-- | Ikeda model (dynamical system, DDE)
ikeda_model2
:: (F -> F) -> (Sample, F) -> Sample
ikeda_model2 f (!(Sample x y), !x_h) = Sample x' y'
where
! x' = recip_epsilon * (-x + (f x_h))
y' = 0
recip_epsilon = 2^(6 :: Int)
-- | Integrate using improved Euler's method (fixed step).
--
-- hOver2 is already half of step size h
-- f is the function to integrate
-- x_i is current argument (x and y)
-- x_h is historical (delayed) value
-- x_h2 it the value after x_h
heun2 :: F -> ParametrizedDelayFunction
-> Sample -> Pair -> Sample
heun2 hOver2 f !x !(Pair x_h x_h2) = x_1
where
! f1 = f (x, x_h)
! x_1' = x ..+.. 2 * hOver2 .*.. f1
! f2 = f (x_1', x_h2)
! x_1 = x ..+.. hOver2 .*.. (f1 ..+.. f2)
initialCond :: Int -> (Sample, Delay, Int)
initialCond nodesN = (initialSampleXY, initialInterval, samplesPerDelay)
where cdi = 1.1247695e-4 :: F -- A fixed point for birefrP
initialInterval = U.replicate samplesPerDelay cdi
samplesPerDelay = nodesN * stepsPerNode
initialSampleXY = Sample 0.0 0.0
integrator
:: PrimitiveM.PrimMonad m =>
(Sample -> Pair -> Sample)
-> Int
-> Int
-> (Sample, (Delay, Input))
-> m (Sample, U.Vector F)
integrator iterate1 len total (xy0, (history0, input)) = do
! v <- UM.new total
go v 0 xy0
history <- U.unsafeFreeze v
-- Zero y value, currently not used
let xy = Sample (history `U.unsafeIndex` (total - 1)) 0.0
return (xy, history)
where
h i = history0 `U.unsafeIndex` i
go !v !i !xy
-- The first iteration
| i == 0 = do
let !r = iterate1 xy (Pair (h 0) (h 1))
UM.unsafeWrite v i (getX r)
go v 1 r
| i < len - 1 = do
let !r = iterate1 xy (Pair (h i) (h $ i + 1))
UM.unsafeWrite v i (getX r)
go v (i + 1) r
| i == total = do
return ()
-- Iterations after the initial history has been exhausted
| otherwise = do
! newX0 <- if i == len - 1
then return (getX xy0)
else UM.unsafeRead v (i - len - 1)
! newX <- UM.unsafeRead v (i - len)
let !r = iterate1 xy (Pair newX0 newX)
UM.unsafeWrite v i (getX r)
go v (i + 1) r
-- Not used in this version
zero :: Input
zero = U.fromList []
nodes :: Int
nodes = 306
main :: IO ()
main = do
let delays = 4000
(sample0, hist0, delayLength) = initialCond nodes
-- Iterator implements Heun's schema
iterator = heun2 (recip 2^(7::Int) :: F) (ikeda_model2 birefrP)
totalComputedIterations = delayLength * delays
-- Calculates all the time trace
(xy1, history1) <- integrator iterator delayLength totalComputedIterations (sample0, (hist0, zero))
putStrLn $ show $ getX xy1
return ()
The nonlinear function (imported) can look like this:
data Parameters = Parameters { beta :: Float
, alpha :: Float
, phi :: Float } deriving Show
paramA :: Parameters
paramA = Parameters { beta = 1.1
, alpha = 1.0
, phi = 0.01 }
birefr :: Parameters -> Float -> Float
birefr par !x = 0.5 * beta' * (1 - alpha' * (cos $ 2.0 * (x + phi')))
where
! beta' = beta par
! alpha' = alpha par
! phi' = phi par
birefrP :: Float -> Float
birefrP = birefr paramA

Haskell numerical integration via Trapezoidal rule results in wrong sign

I've written some code that's meant to integrate a function numerically using the trapezoidal rule. It works, but the answer it produces has a wrong sign. Why might that be?
The code is:
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + partial_sum)
where
h = (b - a) / 1000
most_parts = map f (points (1000-1) h)
partial_sum = sum most_parts
points :: Double -> Double -> [Double]
points x1 x2
| x1 <= 0 = []
| otherwise = (x1*x2) : points (x1-1) x2
Trapezoidal rule
The code is probably inelegant, but I'm only a student of Haskell and would like to deal with the current problem first and coding style matters after that.
Note: This answer is written in literate Haskell. Save it with .lhs as extension and load it in GHCi to test the solution.
Finding the culprit
First of all, let's take a look at integration. In its current form, it contains only summation of function values f x. Even though the factors aren't correct at the moment, the overall approach is fine: you evaluate f at the grid points. However, we can use the following function to verify that there's something wrong:
ghci> integration (\x -> if x >= 10 then 1 else (-1)) 10 15
-4.985
Wait a second. x isn't even negative in [10,15]. This suggests that you use the wrong grid points.
Grid points revisited
Even though you've linked the article, let's have a look at an exemplary use of the trapezoidal rule (public domain, original file by Oleg Alexandrov):
Although this doesn't use a uniform grid, let's suppose that the 6 grid points are equidistant with grid distance h = (b - a) / 5. What are the x coordinates of those points?
x_0 = a + 0 * h (== a)
x_1 = a + 1 * h
x_2 = a + 2 * h
x_3 = a + 3 * h
x_4 = a + 4 * h
x_5 = a + 5 * h (== b)
If we use set a = 10 and b = 15 (and therefore h = 1), we should end up with [10, 11, 12, 13, 14, 15]. Let's check your points. In this case, you would use points 5 1 and end up with [5,4,3,2,1].
And there's the error. points doesn't respect the boundary. We can easily fix this by using pointsWithOffset:
> points :: Double -> Double -> [Double]
> points x1 x2
> | x1 <= 0 = []
> | otherwise = (x1*x2) : points (x1-1) x2
>
> pointsWithOffset :: Double -> Double -> Double -> [Double]
> pointsWithOffset x1 x2 offset = map (+offset) (points x1 x2)
That way, we can still use your current points definition to generate grid points from x1 to 0 (almost). If we use integration with pointsWithOffset, we end up with
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + partial_sum)
where
h = (b - a) / 1000
most_parts = map f (pointsWithOffset (1000-1) h a)
partial_sum = sum most_parts
Tying up loose ends
However, this doesn't take into account that you use all inner points twice in the trapezoid rule. If we add the factors, we end up with
> integration :: (Double -> Double) -> Double -> Double -> Double
> integration f a b =
> h / 2 * (f a + f b + 2 * partial_sum)
> -- ^^^ ^^^
> where
> h = (b - a) / 1000
> most_parts = map f (pointsWithOffset (1000-1) h a)
> partial_sum = sum most_parts
Which yields the correct value for our test function above.
Exercise
Your current version only supports 1000 grid points. Add an Int argument so that one can change the number of grid points:
integration :: Int -> (Double -> Double) -> Double -> Double -> Double
integration n f a b = -- ...
Furthermore, try to write points in different ways, for example go from a to b, use takeWhile and iterate, or even a list comprehension.
Yes it indeed was the points plus you had some factors wrong (the inner points are multiplied by 2) - this is the fixed version of your code:
integration :: (Double -> Double) -> Double -> Double -> Double
integration f a b = h * (f a + f b + innerSum) / 2
where
h = (b - a) / 1000
innerPts = map ((2*) . f . (a+)) (points (1000-1) h)
innerSum = sum innerPts
points :: Double -> Double -> [Double]
points i x
| i <= 0 = []
| otherwise = (i*x) : points (i-1) x
which gives sensible approximations (to 1000 points):
λ> integration (const 2) 1 2
2.0
λ> integration id 1 2
1.5
λ> integration (\x -> x*x) 1 2
2.3333334999999975
λ> 7/3
2.3333333333333335

Resources