Reputation: 83
I want to implement the following function to calculate $(-1)^n / (2n + 1)$ for an integer $n$ in Julia into Haskell.
# Julia
powersign(n) = ifelse(n % 2 == 0, 1, -1)
leibniz_term(n) = powersign(n) / (2n + 1)
println(leibniz_term(10)) # 0.047619047619047616
I write
-- Haskell
powersign 0 = 1
powersign 1 = -1
powersign n = powersign (rem n 2)
leibniz_term n = (powersign n) / (2 * n + 1)
main = print (leibniz_term 10)
but this gives the following errors.
$ ghc -o leibniz_hs leibniz.hs
[1 of 1] Compiling Main ( leibniz.hs, leibniz.o )
leibniz.hs:9:8: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 13 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: print (leibniz_term 10)
In an equation for ‘main’: main = print (leibniz_term 10)
|
9 | main = print (leibniz_term 10)
| ^^^^^^^^^^^^^^^^^^^^^^^
...
Probably, I need to add type annotations to somewhere but I don't know how to do it. How to modify the code to work correctly?
Upvotes: 0
Views: 263
Reputation: 5063
Note that rem
works for Integer
-like numbers, so powersign
should be applied to those (In haskell named Integral
type class). Whereas, division (/)
is real number division. The compiler cannot know if n
in leibniz_term
is Integer-like or Real-like. In haskell you should explicitly convert between number types.
powersign 0 = 1
powersign 1 = -1
powersign n = powersign (rem n 2)
leibniz_term n = fromIntegral (powersign n) / (2 * fromIntegral n + 1)
main = print (leibniz_term 10)
In haskell you have regular number types: Int
, Integer
, Float
and Double
All of them instantiate the Num
Type Class. Meaning that they can perform
(+), (-), (*), signum, negate, ... (and some others)
Then division is different, you have Integral
Type class to perform integer division: quot, rem, etc...
. Members of this type class are Int
and Integer
And Fractional
type class to perform real-number divison: /
. Members of this type class are Float
and Double
To perform math operations like cos
, sin
, log
, etc... you Have the Floating
type class which members are Float
and Double
Coercion is done via fromIntegral
, which transform Int
and Integer
to any other numerical type. Transforming from Double
or Float
back to Integral
is done using common truncate
, ceiling
, etc...
You have another numerical type called Rational
, which is literally a ration between Intergers
. There are some other numerical classes like RealFrac
, RealFloat
. You can get more info here: https://wiki.haskell.org/Converting_numbers and https://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html
Upvotes: 1