How can I sum up Int and Int64? - haskell

I have this code:
tzDiff :: Int
tzDiff = 4 * 60 * 60
mySysTm :: IO Int64
mySysTm = do
st <- getSystemTime
pure $ systemSeconds st
I want to sum up these values.
main = do
a1 <- mySysTm
let res = tzDiff + mySysTm
===>
Couldn't match expected type ‘Int64’ with actual type ‘Int’
How can I sum them up? Without having to change the return type of tzDiff to be Int64 in the function definition because it doesn't need to be Int64
I've tried this - it didn't work due to the same error:
let res = (tzDiff :: Int64) + mySysTm
Why not?

I've tried this - it didn't work due to the same error:
let res = (tzDiff :: Int64) + mySysTm
Because Haskell has a strongly typed type system, which means you can not implicitly convert types from one item to another. Just trying to redeclare it another type will not help either. You should use functions to convert data from one type to another.
We can for example convert an Int to an Int64 with fromIntegral :: (Integral a, Num b) => a -> b:
main = do
a1 <- mySysTm
let res = fromIntegral tzDiff + mySysTm
putStrLn (show res)
because (+) has as type (+) :: Num a => a -> a -> a, so it always sums up two objects of the same type, and these types are members of the Num typeclass. Since it knows that mySysTm is an Int64, it thus knows that the result should be an Int64. Since tzDiff is an Int, it thus knows that it should convert an Int to an Int64.
The fromIntegral is defined in the Num typeclass, so all types that implement the Num typeclass, need to provide a definition for fromIntegral.

let res = (tzDiff :: Int64) + mySysTm
...
Why not?
Because earlier you said
tzDiff :: Int
One value can't be of two different types at the same time.
Use fromIntegral :: (Num b, Integral a) => a -> b instead, like
let res = fromIntegral tzDiff + mySysTm
Because the type of + is (+) :: a -> a -> a, it means that both of its operands must have the same type.
This is already evident in the code even before its compilation, let alone its execution.
fromIntegral is not a run-time type conversion operation. It is a function polymorphic in its return type. The compiler sees it, and interprets the code accordingly.

Related

Why does ghc warn that ^2 requires "defaulting the constraint to type 'Integer'?

If I compile the following source file with ghc -Wall:
main = putStr . show $ squareOfSum 5
squareOfSum :: Integral a => a -> a
squareOfSum n = (^2) $ sum [1..n]
I get:
powerTypes.hs:4:18: warning: [-Wtype-defaults]
• Defaulting the following constraints to type ‘Integer’
(Integral b0) arising from a use of ‘^’ at powerTypes.hs:4:18-19
(Num b0) arising from the literal ‘2’ at powerTypes.hs:4:19
• In the expression: (^ 2)
In the expression: (^ 2) $ sum [1 .. n]
In an equation for ‘squareOfSum’:
squareOfSum n = (^ 2) $ sum [1 .. n]
|
4 | squareOfSum n = (^2) $ sum [1..n]
| ^^
I understand that the type of (^) is:
Prelude> :t (^)
(^) :: (Integral b, Num a) => a -> b -> a
which means it works for any a^b provided a is a Num and b is an Integral. I also understand the type hierarchy to be:
Num --> Integral --> Int or Integer
where --> denotes "includes" and the first two are typeclasses while the last two are types.
Why does ghc not conclusively infer that 2 is an Int, instead of "defaulting the constraints to Integer". Why is ghc defaulting anything? Is replacing 2 with 2 :: Int a good way to resolve this warning?
In Haskell, numeric literals have a polymorphic type
2 :: Num a => a
This means that the expression 2 can be used to generate a value in any numeric type. For instance, all these expression type-check:
2 :: Int
2 :: Integer
2 :: Float
2 :: Double
2 :: MyCustomTypeForWhichIDefinedANumInstance
Technically, each time we use 2 we would have to write 2 :: T to choose the actual numeric type T we want. Fortunately, this is often not needed since type inference can frequently deduce T from the context. E.g.,
foo :: Int -> Int
foo x = x + 2
Here, x is an Int because of the type annotation, and + requires both operands to have the same type, hence Haskell infers 2 :: Int. Technically, this is because (+) has type
(+) :: Num a => a -> a -> a
Sometimes, however, type inference can not deduce T from the context. Consider this example involving a custom type class:
class C a where bar :: a -> String
instance C Int where bar x = "Int: " ++ show x
instance C Integer where bar x = "Integer: " ++ show x
test :: String
test = bar 2
What is the value of test? Well, if 2 is an Int, then we have test = "Int: 2". If it is an Integer, then we have test = "Integer: 2". If it's another numeric type T, we can not find an instance for C T.
This code is inherently ambiguous. In such a case, Haskell mandates that numeric types that can not be deduced are defaulted to Integer (the programmer can change this default to another type, but it's not relevant now). Hence we have test = "Integer: 2".
While this mechanism makes our code type check, it might cause an unintended result: for all we know, the programmer might have wanted 2 :: Int instead. Because of this, GHC chooses the default, but warns about it.
In your code, (^) can work with any Integral type for the exponent. But, in principle, x ^ (2::Int) and x ^ (2::Integer) could lead to different results. We know this is not the case since we know the semantics of (^), but for the compiler (^) is only a random function with that type, which could behave differently on Int and Integer. Consider, e.g.,
a ^ n = if n + 3000000000 < 0 then 0 else 1
When n = 2, if we use n :: Int the if guard could be true on a 32 bit system. This is not the case when using n :: Integer which never overflows.
The standard solution, in these cases, is to resolve the warning using something like x ^ (2 :: Int).

Simple Haskell Average Function Gives Couldn't Match Type Error

All the other average questions I've seen are much more complicated than what I need. I am very new to Haskell and I'm currently working through The Craft of Functional Programming 2nd Edition.
In chapter 3 there is an exercise to write a simple function to average 3 integers. The function type signature is provided and I used it in my solution. I wrote:
averageThree :: Int -> Int -> Int -> Float
averageThree a b c = (a + b + c) / 3
I use ghci for compilation and when I try and load my file I get "Couldn't match expected type Float' with actual typeInt'". How do I fix this error?
The expression a + b + c will have type Int, and / is not even defined for Int. GHC will probably infer that 3 has type Float though. You have to explicitly cast the type in this situation, so you'd need to do
fromIntegral (a + b + c) / 3
The fromIntegral function takes an Integral a => a type like Int or Integer and converts it to a Num b => b type, which could also be Int or Integral, or Float, Double, Complex Double, and even custom numeric types.
You should use Fractional, to support Real division:
averageThree :: Fractional a => a -> a -> a -> a
averageThree a b c = (a + b + c) / 3
(/) :: Fractional a => a -> a -> a, which means / takes two fractional numbers of the same type and returns a fractional number of the same type. You are giving it an Int as an argument, which is not fractional, and asking for a Float as output. You must convert your Int to a Float before giving it to /. Use fromIntegral :: Int -> Float. fromIntegral (a + b + c) / 3. You could also leave off the type signature and ask ghci for the inferred type.

What does has kind 'Constraint' mean in Haskell

I am fresh to Haskell and I am trying to understand the language by writing some code. I am only familiar with very simple instructions on ghci: head, tail, sum, (*), and the like – very simple.
The function I am trying to make is for solving Pythagoras's theorem for vectors of any number of dimensions. This looks something like this: square root (a^2 + b^2 + c^2 ...)
What I can do in ghci in a few lines, which I am trying to make a function is the following:
sq x = x*x
b = map sq [1,2,3]
a = sum b
x = sqrt b
When I do this I try to include a signature of many sorts,
Currently my function looks like this:
mod :: [Num a] => a
mod x = sqrt a
where a = sum [b]
where [b] = map sq [x]
I do not understand the issue when I try to run it:
Expected a constraint, but ‘[Num a]’ has kind ‘*’
• In the type signature:
Main.mod :: [Num a] => a
A few things to adjust:
0) mod isn't a good name for your function, as it is the name of the modulo function from the standard library. I will call it norm instead.
1) The type signature you meant to write is:
norm :: Num a => [a] -> a
[a] is the type of a list with elements of type a. The Num a before the => isn't a type, but a constraint, which specifies that a must be a number type (or, more accurately, that it has to be an instance of the Num class). [Num a] => leads to the error you have seen because, given the square brackets, the type checker takes it as an attempt to use a list type instead of a constraint.
Beyond the Num a issue, you have left out the result type from the signature. The corrected signature reflects that your function takes a list of numbers and returns a number.
2) The Num a constraint is too weak for what you are trying to do. In order to use sqrt, you need to have not merely a number type, but one that is an instance of Floating (cf. leftaroundabout's comment to this answer):
GHCi> :t sqrt
sqrt :: Floating a => a -> a
Therefore, your signature should be
norm :: Floating a => [a] -> a
3) [x] is a list with a single element, x. If your argument is already a list, as the type signature says, there is no need to enclose it in square brackets. Your function, then, becomes:
norm :: Floating a => [a] -> a
norm x = sqrt a
where a = sum b
where b = map sq x
Or, more neatly, without the second where-block:
norm :: Floating a => [a] -> a
norm x = sqrt (sum b)
where b = map sq x
As you are aware, values can be classified by their type. "foo" has type [Char], Just 'c' has type Maybe Char, etc.
Similarly, types can be classified by their kind. All concrete types for which you can provide a value have kind *. You can see this using the :k command in GHCi:
> :k Int
Int :: *
> :k Maybe Int
Maybe Int :: *
Type constructors also have kinds. They are essentially type-valued functions, so their kinds are similar to regular functions.
> :t id
id :: a -> a
> :k Maybe
Maybe :: * -> *
But what is Num a? It's not a type, so it doesn't have kind *. It's not a type constructor, so it doesn't have an arrow kind. It is something new, so a new kind was created to describe it.
> :k Num Int
Num Int :: Constraint
And Num itself is a Constraint-valued function: it takes a value of kind * and produces a Constraint:
> :k Num
Num :: * -> Constraint
A thing with kind Constraint is used to specify the typeclass that a particular type must be an instance of. It is the value that can occur before => in a type signature. It is also the "argument" to the instance "function":
instance Num Int where
...

Haskell do-block return error

I have a simple function:
func :: Int
func = do
x <- 1
return x
But I got an error message as follows:
Couldn't match type ‘m0 b0’ with ‘Int’
What's wrong with my function?
There are two problems with your code:
The right side of <- must have the type m a where a is an arbitrary type (that then becomes the type of the left side) and m is the monad that the do-block belongs to. In your case the type of the right side is 1, which does not have that type.
If all you want to do is to bind a value to x, you need to use let x = 1, not <-.
The type of return is Monad m => a -> m a, so if we take the type of x to be Int, the type of return x is Monad m => m Int. But according to your type signature, you just want the type to be Int, not m Int. Therefore you shouldn't use return (or do-notation for that matter).
The correct way to write the definition that you're trying to write would be:
f = 1
or if you want to have a local x
f =
let x = 1 in
x
or
f = x
where x = 1

How to declare function (type misunderstanding Maybe)

I need a function which works like:
some :: (Int, Maybe Int) -> Int
some a b
| b == Nothing = 0
| otherwise = a + b
Use cases:
some (2,Just 1)
some (3,Nothing)
map some [(2, Just 1), (3,Nothing)]
But my code raise the error:
The equation(s) for `some' have two arguments,
but its type `(Int, Maybe Int) -> Int' has only one
I don't understand it.
Thanks in advance.
When you write
foo x y = ...
That is notation for a curried function, with a type like:
foo :: a -> b -> c
You have declared your function to expect a tuple, so you must write it:
some :: (Int, Maybe Int) -> Int
some (x, y) = ...
But Haskell convention is usually to take arguments in the former curried form. Seeing funcitons take tuples as arguments is very rare.
For the other part of your question, you probably want to express it with pattern matching. You could say:
foo :: Maybe Int -> Int
foo Nothing = 0
foo (Just x) = x + 1
Generalizing that to the OP's question is left as an exercise for the reader.
Your error doesn't come from a misunderstanding of Maybe: The type signature of some indicates that it takes a pair (Int, Maybe Int), while in your definition you provide it two arguments. The definition should thus begin with some (a,b) to match the type signature.
One way to fix the problem (which is also a bit more idiomatic and uses pattern matching) is:
some :: (Int, Maybe Int) -> Int
some (a, Nothing) = a
some (a, Just b) = a + b
It's also worth noting that unless you have a really good reason for using a tuple as input, you should probably not do so. If your signature were instead some :: Int -> Maybe Int -> Int, you'd have a function of two arguments, which can be curried. Then you'd write something like
some :: Int -> Maybe Int -> Int
some a Nothing = a
some a (Just b) = a + b
Also, you might want to add the following immediate generalization: All Num types are additive, so you might aswell do
some :: (Num n) => n -> Maybe n -> n
some a Nothing = a
some a (Just b) = a + b
(I've violated the common practice of using a, b, c... for type variables so as not to confuse the OP since he binds a and b to the arguments of some).

Resources