I need to call floor()
on a value, which is only constrained to be of class Floating
, but floor()
requires RealFrac
.
How can I do this?
I'm perfectly willing to call abs()
before calling floor()
, but this alone seems insufficient to solve my constraint conflict.
And coerce
complains that the two representations cannot be assumed equivalent, which isn't surprising.
It seems what I need is a function with type signature:
(Floating a, RealFrac b) => a -> b
And it seems (to me) perfectly legitimate to give some augmented version of abs()
this signature.
Alas, a Hoogle search on the above type signature left me empty handed.
Any thoughts?
Thanks.
:)
In Haskell, every statement is considered as a mathematical expression and the category of this expression is called as a Type. You can say that "Type" is the data type of the expression used at compile time. To learn more about the Type, we will use the ":t" command.
Haskell has two integral types, namely Int and Integer . Int is the type of limited-precision integers; this means that there is a smallest integer of type Int , namely minBound , and a greatest integer of type Int , namely maxBound .
The Eq class defines equality ( == ) and inequality ( /= ). All the basic datatypes exported by the Prelude are instances of Eq , and Eq may be derived for any datatype whose constituents are also instances of Eq . The Haskell Report defines no laws for Eq .
The shows functions return a function that prepends the output String to an existing String . This allows constant-time concatenation of results using function composition.
Consider the following instance of Floating
:
import Control.Applicative
instance (Num a) => Num (e -> a) where
(+) = liftA2 (+)
(*) = liftA2 (*)
(-) = liftA2 (-)
abs = fmap abs
signum = fmap signum
negate = fmap negate
fromInteger = pure . fromInteger
instance (Fractional a) => Fractional (e -> a) where
fromRational = pure . fromRational
recip = fmap recip
(/) = liftA2 (/)
instance (Floating a) => Floating (e -> a) where
pi = pure pi
exp = fmap exp
log = fmap log
sin = fmap sin
cos = fmap cos
asin = fmap asin
acos = fmap acos
atan = fmap atan
sinh = fmap sinh
cosh = fmap cosh
asinh = fmap asinh
acosh = fmap acosh
atanh = fmap atanh
Demo:
main :: IO ()
main = do
print (sqrt sqrt 81)
let f = sin^2 + cos^2
print (f 42)
(This outputs 3.0000000000000004
and 1.0
.)
This makes functions an instance of Floating
, but the code generalizes to all types that are Monad
s or Applicative
s.
Your hypothetical function would need to have the type
(Floating a, RealFrac b) => (e -> a) -> b
in this instance. We could set a
and b
to Double
:
(e -> Double) -> Double
How do you implement that operation?
Remember that I said this generalizes to all Applicatives? We can replace e ->
by IO
in the above instances. Then the type you end up with gets even worse:
IO Double -> Double
The problem is that Floating
can be anything that supports e.g. exp
or sin
operations (which could be purely symbolic operations e.g. on a syntax tree) while RealFrac
must be a number (or something convertible to a number).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With