Currently brushing up on my Haskell by doing Codewars. I have made the following code,
import Data.Char(digitToInt)
calc :: String -> Int
calc s = sum $ map (\i -> (digitToInt i)^n) s
where n = length s
narcissistic :: Integral n => n -> Bool
narcissistic n = calc s == n
where s = show n
Which produces,
Couldn't match expected type 'Int' with actual type 'n'
'n' is a rigid type variable bound by
the type signature for:
narcissistic :: forall n. Integral n => n -> Bool
To my knowledge this is caused by the fact that the narcissistic function taking an input n which is within the Integral type class (Int or Integer). However the calc function produces an Int. Thus I cannot compare the result of calc and the n.
My question is thus, what would be the ideal way to work with these type classes, and how would I be able to implement a function such as calc which would possibly work with the Integral class type (unable to do so because of the digitToInt?).
calc specifically returns an Int, which means == also expects an Int, but you are only providing an Integral n => n value. Sure, narcissistic could be called with an Int, but it could just as well be called with an Integer or some other type with an Integral instance.
To make the comparison, you need a common type. You can use toInteger :: Integral a => a -> Integer on both calc s and n to get Integer values that can be compared directly.
narcissistic :: (Show n, Integral n) => n -> Bool
narcissistic n = toInteger (calc s) == toInteger n
where s = show n
Note that Integral does not imply Show; you need to add that to the constraints as well.
However... you can't know that the number calc computes from the String input will fit in an Int; you should return an Integer in the first place, then use fromIntegral :: (Integral a, Num b) => a -> b to turn n into an Integer.
calc :: String -> Integer
calc s = sum $ map (\i -> (fromIntegral (digitToInt i))^n) s
where n = length s
narcissistic :: Integral n => n -> Bool
narcissistic n = calc s == fromIntegral n
where s = show n
How would I be able to implement a function such as calc which would possibly work with the Integral class type (unable to do so because of the digitToInt?).
You can use fromIntegral to convert that Int to any Integral (or even more generically, any Num, but we don't need that here):
calc :: Integral i => String -> i
calc s = sum $ map (\i -> (fromIntegral $ digitToInt i)^n) s
where n = length s
Related
This question already has an answer here:
Haskell multiply Int and real number
(1 answer)
Closed 8 years ago.
I am trying out Haskell following 'Haskell the hardway' and I am stuck at understanding the basic type system. I have the following code and the haskell is complaining it can't process the function.
f3 :: Num -> Int -> Num
f3 x y = x + y
I take it, it has to do something with currying or the basic model where haskell converts f x y to (f x) y but if I want to pass and Int to Y, can I do it? if I can how would I do it?
I take it, it has to do something with currying or the basic model where haskell converts f x y to (f x) y
No. It has — as almost always in the Haskell world — to do with types. First of all, Num is a typeclass, not a type. Types can be instances of a typeclass, for example Int, Integer and Double are instances of Num. Now, lets have a look at plus' type:
(+) :: Num a => a -> a -> a
Aha! It takes two arguments of type a, and returns an a, where a needs to be an instance of Num (also called constraint).
Now we have enough information to revisit f3:
f3_wrong_sig :: Num -> Int -> Num
After the discussion above, it's clear that f3_wrong_sig has a wrong signature. Instead of Num, it needs a constrained by Num:
f3_wrong_implementation :: Num a => a -> Int -> a
f3_wrong_implementation x y = x + y
However, if we remember the type of (+), x + y is only possible for a and Int being equivalent (also written a ~ Int). We need a way to get create another numeric type from Int: we need a function Num a => Int -> a. Lets inspect some information about Int in GHCi:
ghci> :i Int
data Int = GHC.Types.I# GHC.Prim.Int# -- Defined in `GHC.Types'
-- omitted
instance Integral Int -- Defined in `GHC.Real'
instance Num Int -- Defined in `GHC.Num'
-- omitted
Int is not only an instance of Num, but also of Integral. A quick hoogle search gives us fromIntegral :: (Integral b, Num a) => b -> a, which we can plug in and finally get what we want:
f3 :: Num a => a -> Int -> a
f3 x y = x + fromIntegral y
At that point, we can also take a final step to make this even more general, since fromIntegral works for any Integral:
f3_general :: (Integral b, Num a) => a -> b -> a
f3_general x y = x + fromIntegral y
This is also the type GHC would infer.
Next reasons:
1) There is no such type as Num
2) Both arguments of (+) function must have the same type
Possible solutions:
f3 :: Int -> Int -> Int
f3 :: Double -> Double -> Double
f3 :: Num a => a -> a -> a -- could add any numerical type
I defined the custom exponentiation exp' function in GHCi as:
let exp' x = sum $ take 100 [(x**k) / factorial k | k <- [0..]]
which yields the following type signature:
#> :t exp'
exp' :: (Enum a, Floating a) => a -> a
However, I would have expected it to match that of the exp function, i.e.
#> :t exp
exp :: Floating a => a -> a
Can anybody explain the Enum a => a type constraint of my exp' function? Why isn't it just Floating a => a?
Thanks.
It originates from the k <- [0..] - that desugars to use the Enum class.
It then propagates into the final type signature because you're using (**) for exponentiation which expects its arguments to be the same type:
(**) :: Floating a => a -> a -> a
One option is to use (^) for exponentiation instead:
(^) :: (Integral b, Num a) => a -> b -> a
You'll also need to convert factorial k to the right type, with something like fromIntegral:
exp' x = sum $ take 100 [(x^k) / fromIntegral (factorial k) | k <- [0..]]
It's possibly a better fit for this case because your exponents will be integers, although it may be a bit less efficient as it uses repeated multiplication (logarithmic in the exponent) rather than constant-time floating point operations.
Alternatively (as suggested in a comment), to stick with (**), use fromIntegral to move from an enumeration over Int to the actual type you are working with:
let exp' x = sum $ take 100 [(x**fromIntegral k) / fromIntegral (factorial k)
| k <- [0..]]
[0..] is converted into
enumFrom 0
and enumFrom has type Enum a => a -> [a] so the compiler infers that k must be an enum type.
I am trying to write a function that computes ex (for the first 10 terms) given an integer `x.
The series expansion for ex is given by
1 + x + x2/2! + x3/3! + x4/4! + ....
The function itself was fairly easy to write, but I can't seem to understand Haskell type rules for division, i.e I want to divide an integer by a larger integer and get a floating-point result:
Here is what I have so currently
_eToX :: (Fractional a, Integral a) => a -> a -> a
_eToX x 0 = 1.0
_eToX x 1 = x
_eToX x n = ( fromIntegral(x^n) / fromIntegral(factorial n) ) + _eToX x (n - 1)
What I am doing above here makes sense to me, compute two integer results (x^n and factorial n) then evaluate them in a Floating point context using fromIntegral and /. This function however returns this error:
1. Could not deduce (a ~ Integer)
from the context (Fractional a, Integral a)
bound by the type signature for
_eToX :: (Fractional a, Integral a) => a -> a -> a
at /run-r4AWbVU9Fyph0OVhK3Dm/solution.hs:9:10-50
`a' is a rigid type variable bound by
the type signature for
_eToX :: (Fractional a, Integral a) => a -> a -> a
at /run-r4AWbVU9Fyph0OVhK3Dm/solution.hs:9:10
In the return type of a call of `factorial'
In the second argument of `(/)', namely `factorial n'
In the first argument of `(+)', namely `(x ^ n / factorial n)'
2. No instance for (Integral Double) arising from a use of `f'
Possible fix: add an instance declaration for (Integral Double)
In the expression: f
In the second argument of `($)', namely
`f $ map (read :: String -> Double) $ lines inputdata'
In the second argument of `($)', namely
`map show $ f $ map (read :: String -> Double) $ lines inputdata'
I am running the function with this main function:
main = do
n <- readLn :: IO Int -- n doesnt really matter here because of getContents
inputdata <- getContents
mapM_ putStrLn $ map show $ f $ map (read :: String -> Double) $ lines inputdata
This type:
_eToX :: (Fractional a, Integral a) => a -> a -> a
doesn't make sense. You want the first argument and result to be Fractional, but the second argument, corresponding to the sequence position, should be Integral. Change the type to:
_eToX :: (Fractional a, Integral b) => a -> b -> a
Now there's a different error, arising from a missing Integral instance because of fromIntegral (x^n). ghci shows
Prelude> :t (^)
(^) :: (Integral b, Num a) => a -> b -> a
So it's not necessary to even use fromIntegral here, as the output is already the correct type. The final function is:
_eToX :: (Fractional a, Integral b) => a -> b -> a
_eToX x 0 = 1.0
_eToX x 1 = x
_eToX x n = ( (x^n) / fromIntegral(factorial n) ) + _eToX x (n - 1)
Here is what you are probably looking for.
eToX :: Integral a => Double -> a -> Double
eToX x 0 = 1
eToX x 1 = 1 + x
eToX x n = x^^n / (fromIntegral $ factorial n) + eToX x ( n - 1)
(^^) :: (Fractional a, Integral b) => a -> b -> a
You didn't want n and x to be the same. See how that power function does it.
Oh, and your equation was wrong for n = 1 you should have 1 + x
Is your f the given _eToX? your _eToX takes two arguments but you apply f to only one.
This is fine as long as you only want a a partial application.
Concerning the error messages you should check the following:
What is the type of your factorial it seems to be something that has an Integer as an result and not something that implements the Typclasses Integral and fractional
You added a type annotation for your read function, s.t. it returns a Double Which is not an instance of Integral. But your f seems to take something as an argument which is an instance of Integral.
I am new to Haskell from a C++ and Java background. Occassionally, I have trouble with Haskell's type system. My current error is with this piece of code:
countIf :: (Integral b) => [a] -> (a -> Bool) -> b
countIf [] p = 0
countIf (x:xs) p
| p x = 1 + countIf xs p
| otherwise = countIf xs p
isRelativelyPrime :: (Integral a) => a -> a -> Bool
isRelativelyPrime m n = gcd m n == 1
phi :: (Integral a, Integral b) => a -> b
phi n = countIf [1..(n - 1)] (isRelativelyPrime n)
main = print [(n, phi n, ratio) | n <- [1..10], let ratio = (fromIntegral (phi n)) / n]
The error message is
prog.hs:13:60:
Ambiguous type variable `b' in the constraints:
`Fractional b' arising from a use of `/' at prog.hs:13:60-85
`Integral b' arising from a use of `phi' at prog.hs:13:75-79
Probable fix: add a type signature that fixes these type variable(s)
13:60 is just before the usage of fromIntegral in the let binding in my list comprehension in main. I'm still trying to get used to ghc's error messages. I am unable to decipher this particular one in order to figure out what I need to change to get my code to compile. Any help will be greatly appreciated. Thanks.
This is an example of a common beginner mistake: excessively polymorphic code.
You've made your code as general as possible, e.g.
phi :: (Integral a, Integral b) => a -> b
this will take any integral type to any other integral type, via the phi transformation.
Such polymorphic code is great for libraries, but not so great for type inference. I'd put money that you just want this to work on Integers, so we can go ahead an give a more accurate type,
countIf :: [Integer] -> (Integer -> Bool) -> Integer
countIf [] p = 0
countIf (x:xs) p
| p x = 1 + countIf xs p
| otherwise = countIf xs p
isRelativelyPrime :: Integer -> Integer -> Bool
isRelativelyPrime m n = gcd m n == 1
phi :: Integer -> Integer
phi n = countIf [1..(n - 1)] (isRelativelyPrime n)
main = print [ (n, phi n, ratio)
| n <- [1..10], let ratio = (fromIntegral (phi n)) ]
and the type error just goes away.
You may even see performance improvements (particularly if you specialize to Int).
You need to call fromIntegral on n as well since Haskell doesn't automatically convert from integral types, which you already seem to know since you called fromIntegral (phi n). I make this mistake all the time, not a big deal!
Trying to use hmatrix, to create a zero marix.
For some reason, when I try this on command line, it works:
buildMatrix 2 3 (\(r,c) -> fromIntegral 0)
However, when I try to do the same thing in my code:
type Dim = (Int, Int)
buildFull :: Matrix Double -> Vector Int -> Vector Int -> Dim -> Int
buildFull matrix basic nonbasic (m, n) = do
-- Build mxn matrix of zeroes
let f = buildMatrix m n (\(r,c) -> fromIntegral 0)
m
it fails:
Pivot.hs:23:17:
Ambiguous type variable `a0' in the constraints:
(Element a0) arising from a use of `buildMatrix'
at Pivot.hs:23:17-27
(Num a0) arising from a use of `fromIntegral' at Pivot.hs:23:44-55
Probable fix: add a type signature that fixes these type variable(s)
In the expression: buildMatrix m n (\ (r, c) -> fromIntegral 0)
In an equation for `f':
f = buildMatrix m n (\ (r, c) -> fromIntegral 0)
In the expression:
do { let f = buildMatrix m n (\ (r, c) -> ...);
m }
Failed, modules loaded: none.
You can also use konst from Numeric.Container:
import Numeric.LinearAlgebra
m = konst 0 (2,3) :: Matrix Double
v = konst 7 10 :: Vector (Complex Float)
type Dim = (Int, Int)
buildFull :: Matrix Double -> Vector Int -> Vector Int -> Dim -> Int
buildFull matrix basic nonbasic (m, n) = do
-- Build mxn matrix of zeroes
let f = buildMatrix m n (\(r,c) -> fromIntegral 0)
m
First, to use do-notation, you need a monadic return type, so that won't compile even after fixing the ambiguous element type (as I was reminded by #Carl, it would be okay here while there's only a single expression so that no (>>=) or (>>) is needed).
Concerning the element type, in the let-binding, there is no way to find out which type to use, whether fromIntegral should return Double, Integer or whatever. Often the type to be used can be inferred from context, by the expressions it is used in. Here, f is nowhere used, so there's no context. Hence in this situation, you have to specify the type by a signature, that can be
let f :: Matrix Double
f = buildMatrix m n (const 0)
or
let f = buildMatrix m n (\_ -> (0 :: Double))
if you want the element type o be Double.
Replace fromIntegral 0 with 0::Double. Otherwise the sort of matrix you want to build is underconstrained. At the prompt, extended defaulting rules are probably solving that problem for you.