haskell - Is it square check -
i trying write function check if argument square of integer:
issquare :: int -> bool issquare x = truncate(sqrt(x)) * truncate(sqrt(x)) == x
when loading function error:
prelude> :load "some.hs" [1 of 1] compiling main ( some.hs, interpreted ) some.hs:2:13: no instance (realfrac int) arising use of `truncate' @ some.hs:2:13-29 possible fix: add instance declaration (realfrac int) in first argument of `(*)', namely `truncate (sqrt (x))' in first argument of `(==)', namely `truncate (sqrt (x)) * truncate (sqrt (x))' in expression: truncate (sqrt (x)) * truncate (sqrt (x)) == x some.hs:2:22: no instance (floating int) arising use of `sqrt' @ some.hs:2:22-28 possible fix: add instance declaration (floating int) in first argument of `truncate', namely `(sqrt (x))' in first argument of `(*)', namely `truncate (sqrt (x))' in first argument of `(==)', namely `truncate (sqrt (x)) * truncate (sqrt (x))' failed, modules loaded: none.
but if try execute:
prelude> truncate(sqrt(9))*truncate(sqrt(9))==9 true
all fine.
why error , how fix ?
you're getting errors because of type mismatches. type of sqrt
sqrt :: floating => -> a
, , type of truncate
truncate :: (realfrac a, integral b) => -> b
. former says sqrt
takes input floating-point number, , returns 1 of same type output; latter says can truncate real fractional number1 integral number. however, assert x
int
, , int
isn't floating-point number. thus, second error: "no instance (floating int)
arising use of `sqrt
'". says because of sqrt x
, wanted int
floating-point number, there's no definition that. first error similar: since sqrt :: floating => -> a
, output same input, you're trying call truncate
on integer. of course makes no sense, since int
not realfrac
, , that's why first error. fixing easy:
issquare :: int -> bool issquare x = let x' = truncate $ sqrt (fromintegral x :: double) in x'*x' == x
the fromintegral
function has type fromintegral :: (integral a, num b) => -> b
; can convert integral number any number @ all. why need tell haskell want produce double
; it'd default anyway, it's nice clear (though not necessary). double
instance both of floating
, realfrac
, can sqrt
, truncate
it. rearranged code little; way there how i'd write it, since way compute truncation
, sqrt
once. also, note if remove type signature, haskell infer more general type issquare :: integral => -> bool
, since never assume x
precisely int
.
the reason truncate(sqrt(9))*truncate(sqrt(9))==9
returned true
because of type of 9
. can ask ghci tell this:
prelude> :t 9 9 :: (num t) => t
in haskell, integral numeric literals have type num t => t
(9.0
, or number decimal point, has type fractional t => t
). means can any kind of number @ all, thing. otherwise, 9
have int
or integer
, , defining new number types—or using both int
, integer
!2—would royal pain. thus, when write truncate(sqrt(9))
, ghci determines 9
must instance of floating
(from sqrt
) , realfrac
(from truncate
), defaults double
, making work. defaulting standard behavior numeric types (it's why leave out :: double
in definition of issquare
), though not else (except in ghci, extends convenience). since 9
isn't int
, x
is, don't need convert 9
, need convert x
.
1: difference between floating
, realfrac
that, instance, complex double
instance of floating
not realfrac
, , rational
instance of realfrac
not floating
. float
, double
instances of both.
2: in case haven't come across this, difference int
finite-precision, , integer
arbitrary-precision.
Comments
Post a Comment