Can I make a polymorphic `mult` function, that takes any numeric type? - haskell

I'm learning Haskell. This is the very first program that I've ever wrote and I just thought of making a simple function that returns the product of the given arguments.
mult :: a -> a -> a
mult x y = x * y
When I write it this way, I get an "inferred type" error.
ERROR "uno.hs":5 - Inferred type is not general enough
*** Expression : mult
*** Expected type : a -> a -> a
*** Inferred type : Integer -> Integer -> Integer
It wants me to write it this way:
mult :: Int -> Int -> Int
mult x y = x * y
...which works perfectly fine, but then I wonder... can't this function work on Floats as well?
It can.
mult :: Float -> Float -> Float
mult x y = x * y
--then
mult 4 5 == 20.0
Finally, I wonder:
Can I make a polymorphic mult function, that takes any numeric type?
Why does the parser infers Integrer from a function that also works with other types?
I found no answers so far, yet this seems like a simple question. I'll be grateful for help me.

Short answer: mult :: Num a => a -> a -> a and it picked Integer because it felt like it was a good choice.
Long answer:
mult can't be a -> a -> a because that would mean it works on every type a, including String, Char, Bool, etc. The Num a => part is called a constraint, and it restricts what a can be by requiring that it is an instance of the Num type class. It's like saying "this function works on any type, as long as that type has the properties (has an instance) of this specific type class". The properties for the Num type class are defined in the standard library, linked below.
It's worth noting that the type of (*) itself is Num a => a -> a -> a, and that your function mult could also have been defined as mult = (*).
The reason it told you to use Integer -> Integer -> Integer is because the default for Num is Integer. You should never rely on this being the case, and should instead write out the full, type class constrained type signature.
When you specified the type signature Float -> Float -> Float, the compiler specializes the function to only work on Floats, as you would expect. This resolves the "over-promising" problem arising from a -> a -> a by choosing a specific type for a that the compiler knows has a Num instance.
Read more about type classes here, and the specific definition of Num is documented here and the code is linked on the side of the page. (Not enough rep to post the link directly)

Related

can't use pattern matching with datatypes defined using GADT in haskell

I'm trying to define a Complex datatype, and I want the constructors to be able to take any number as instance, so I would like to use a generic type as long as it does implement a Num instance
I'm usind GADTs in order to do so since to my understanding the DataTypeContexts language extension was a "misfeature" even if I think that would have been useful in this case...
In any case this is my code:
data Complex where
Real :: ( Num num, Show num ) => num -> Complex
Imaginary :: ( Num num, Show num ) => num -> Complex
Complex :: ( Num num, Show num ) => num -> num -> Complex
real :: ( Num num, Show num ) => Complex -> num
real (Real r) = r
real (Imaginary _i ) = 0
real (Complex r _i ) = r
here the real implementation gives the following error:
Couldn't match expected type ‘num’ with actual type ‘num1’
‘num1’ is a rigid type variable bound by
a pattern with constructor:
Real :: forall num. (Num num, Show num) => num -> Complex,
in an equation for ‘real’
at <...>/Complex.hs:29:7-12
‘num’ is a rigid type variable bound by
the type signature for:
real :: forall num. (Num num, Show num) => Complex -> num
at <...>/Complex.hs:28:1-47
• In the expression: r
In an equation for ‘real’: real (Real r) = r
• Relevant bindings include
r :: num1
(bound at <...>/Complex.hs:29:12)
real :: Complex -> num
(bound at <...>/Complex.hs:29:1)
which to my understanding is due to the return type do be interpreted as different...
so I tried removing the type definition and letting ghc do his magic with the type but turns out the type signature was the same...
can anyone please explain to me what is wrong here?
Problem is, these definitions allow you to choose different types when (1) constructing a Complex value and when (2) applying the real function. These two situations are not connected to each other in any way, so there is nothing to force the type to be the same between them. For example:
c :: Complex
c = Real (42 :: Int)
d :: Double
d = real c
The definition of d requires the real function to return a Double, but there is no Double wrapped inside of c, there is only Int.
As for solutions, there are two possible ones: (1) establish a connection between these two points, forcing the type to be the same, and (2) allow the type inside to be converted to any other numeric type.
To establish a type-level connection between two points, we need to use a type that is present at both points. What type would that be? Quite obviously, that's the type of c. So we need to make the type of c somehow convey what's wrapped inside it:
data Complex num = Real num | Imaginary num | Complex num num
real :: Complex num -> num
real = ...
-- Usage:
c :: Complex Int
c = Real 42
d :: Int
d = real c
Note that I don't actually need GADTs for this.
To allow type conversion, you'll need to require another type class for the num type. The class Num has a way to convert from any integral type, but there is no way to convert to any such type, because it doesn't make sense: 3.1415 can't be meaningfully converted to an integral type.
So you'll have to come up with your own way to convert, and implement it for all allowed types too:
class Convert a where
toNum :: Num n => a -> n
data Complex where
Real :: ( Num num, Show num, Convert num ) => num -> Complex
...
real :: Num num => Complex -> num
real (Real r) = toNum r
...
Just to be clear, I consider the second option quite insane. I only provided it for illustration. Don't do it. Go with option 1.

Syntax in Functions (Expected kind `* -> Constraint', but `Int' has kind `*') [duplicate]

This question already has answers here:
`String' is applied to too many type arguments
(2 answers)
Closed 2 years ago.
I'm starting to learn Haskell and I'm struggling with syntax in Functions. I'm trying to create a function that receives a Number 'e' and a Number 'n', returning a list with of 'n' times 'e'.
Example: repn 3 5 would return [3,3,3,3,3]:
repn :: Int a => a -> a -> [a]
repn e n
| n >= 1 = (take n (repeat e))
| otherwise = []
But I'm getting this error:
* Expected kind `* -> Constraint', but `Int' has kind `*'
* In the type signature: replica :: Int a => a -> a
As a rule of thumb, writing something of the form Foo a => ... only makes sense of Foo is a type class. Unlike in OO languages, a class and a type in Haskell are completely different things. Int is a type, therefore it cannot be used in this way; instead you should simply use
repn :: Int -> Int -> [Int]
...though actually there's no reason to restrict the list-element type at all, the signature could as well be
repn :: a -> Int -> [a]
Alternatively, you can use a type class: the class of “int-like types” is Integral. Then you can't use take directly, as that is restricted to Int for the counter argument; however you can convert any integral type to Int:
repn :: Integral n => a -> n -> [a]
repn e n = take (fromIntegral n) $ repeat e
-- Note no case distinction is needed, because `take` already yields
-- an empty list if `n<1`.
Your type definition is not correct. The double arrow is used to show required typeclasses (aka kind * -> Constraint), or a constraint on types. However, Int is itself a type (aka kind *).
You can't specify types in this way. In your implementation, n must be an Int, but e could be anything. Since you specify that it should be a number, though, you can constrain it with the Num typeclass. The correct version of your signature therefore is:
repn :: Num a => a -> Int -> [a]
If you want e to be constrained to an Int, then your signature should be
repn :: Int -> Int -> [Int]
If you don't need any constraints on e, your signature can be
repn :: a -> Int -> [a]
These are all valid type signatures for the function you have written. (Though in actual code, I would just point you to the builtin replicate function.)

Difference between -> and => symbols. What do they mean?

In Haskell, when we talk type declaration.
I've seen both -> and =>.
As an example: I can make my own type declaration.
addMe :: Int -> Int -> Int
addMe x y = x + y
And it works just fine.
But if we take a look at :t sqrt we get:
sqrt :: Floating a => a -> a
At what point do we use => and when do we use ->?
When do we use "fat arrow" and when do we use "thin arrow"?
-> is for explicit functions. I.e. when f is something that can be written in an expression of the form f x, the signature must have one of these arrows in it†. Specifically, the type of x (the argument) must appear to the left of a -> arrow.
It's best to not think of => as a function arrow at all, at least at first‡. It's an implication arrow in the logical sense: if a is a type with the property Floating a, then it follows that the signature of sqrt is a -> a.
For your addMe example, which is a function with two arguments, the signature must always have the form x -> y -> z. Possibly there can also be a q => in front of that; that doesn't influence the function-ishness, but may have some saying in what particular types are allowed. Generally, such constraints are not needed if the types are already fixed and concrete. Like, you could in principle impose a constraint on Int:
addMe :: Num Int => Int -> Int -> Int
addMe x y = x + y
...but that doesn't really accomplish anything, because everybody knows that the particular type Int is an instance of the Num class. Where you need such constraints is when the type is not fixed but a type variable (i.e. lowercase), i.e. if the function is polymorphic. You can't just write
addMe' :: a -> a -> a
addMe' x y = x + y
because that signature would suggest the function works for any type a whatsoever, but it can't work for all types (how would you add, for example, two strings? ok perhaps not the best example, but how would you multiply two strings?)
Hence you need the constraint
addMe' :: Num a => a -> a -> a
addMe' x y = x + y
This means, you don't care what exact type a is, but you do require it to be a numerical type. Anybody can use the function with their own type MyNumType, but they need to ensure that Num MyNumType is fulfilled: then it follows that addMe' can have signature MyNumType -> MyNumType -> MyNumType.
The way to ensure this is to either use a standard type which you know to be numerical, for instance addMe' 5.9 3.7 :: Double would work, or give an instance declaration for your custom type and the Num class. Only do the latter if you're sure it's a good idea; usually the standard num types are all you'll need.
†Note that the arrow may not be visible in the signature: it's possible to have a type synonym for a function type, for example when type IntEndofunc = Int -> Int, then f :: IntEndofunc; f x = x+x is ok. But you can think of the typedef as essentially just a syntactic wrapper; it's still the same type and does have the arrow in it.
‡It so happens that logical implication and function application can be seen as two aspects of the same mathematical concept. Furthermore, GHC actually implements class constraints as function arguments, so-called dictionaries. But all this happens behind the scenes, so if anything they're implicit functions. In standard Haskell, you will never see the LHS of a => type as the type of some actual argument the function is applied to.
The "thin arrow" is used for function types (t1 -> t2 being the type of a function that takes a value of type t1 and produces a value of type t2).
The "fat arrow" is used for type constraints. It separates the list of type constraints on a polymorphic function from the rest of the type. So given Floating a => a -> a, we have the function type a -> a, the type of a function that can take arguments of any type a and produces a result of that same type, with the added constraint Floating a, meaning that the function can in fact only be used with types that implement the Floating type class.
the -> is the constructor of functions and the => is used to constraints, a sort of "interface" in Haskell called typeclass.
A little example:
sum :: Int -> Int -> Int
sum x y = x + y
that function only allows Int types, but if you want a huge int or a small int, you probably want Integer, and how to tell it to use both?
sum2 :: Integral a => a -> a -> a
sum2 x y = x + y
now if you try to do:
sum2 3 1.5
it will give you an error
also, you may want to know if two data are equals, you want:
equals :: Eq a => a -> a -> Bool
equals x y = x == y
now if you do:
3 == 4
that's ok
but if you create:
data T = A | B
equals A B
it will give to you:
error:
• No instance for (Eq T) arising from a use of ‘equals’
• In the expression: equals A B
In an equation for ‘it’: it = equals A B
if you want for that to work, you must just do:
data T = A | B deriving Eq
equals A B
False

No instance for (Floating Integer) arising from a use of '**'?

I have the following Haskell code:
two :: Integer -> Integer
two i = toInteger(2 ** i)
Why isn't it working?
(**) requires floating point input based on the function signature:
(**) :: Floating a => a -> a -> a
toInteger on the other hand requires input that is integral in nature:
toInteger :: Integral a => a -> Integer
Therefore, you cannot reconcile the two the way you use it. That said, since you seem to be expecting integer input anyway, you might consider using (^) instead, like so:
two :: Integer -> Integer
two i = 2 ^ i
As #leftaroundabout correctly points out in the comments, (^) will fail for negative values of i. This can be resolved by checking for value and handling in an alternate manner, something like this:
two :: Integer -> Integer
two i = if i > 0 then 2 ^ i else floor (2 ** fromIntegral i)
Use ^ instead:
two i = 2 ^ i
And then there is no need for to cast the result back to an Integral type.
The reason this...
two :: Integer -> Integer
two i = toInteger(2 ** i)
...doesn't work is because you've declared i to be an integer, and if we look at the type of (**)...
Prelude> :t (**)
(**) :: Floating a => a -> a -> a
... all it's arguments are of the same type, and that type has to be an instance of the Floating type-class. Integer is not an instance of Floating. This is what "No instance of (Floating Integer)" means.
The simplest solution is to use ^ as ErikR suggests. It raises a number to an integral power.
(^) :: (Integral b, Num a) => a -> b -> a
If you want to work through using ** to learn a bit more, keep reading.
So we need to convert your integer into a type which is an instance of Floating. You can do this with fromIntegral. If we do this:
two :: Integer -> Integer
two i = toInteger(2 ** fromIntegral(i))
...we still get a load of error messages complaining that various types are ambiguous. These aren't as clear as the first message, but the issue is the use of toInteger which becomes apparent if we look at it's type.
Prelude> :t toInteger
toInteger :: Integral a => a -> Integer
As we're passing the result of ** to toInteger, and that is a Floating, not an Integral, toInteger is the wrong function. round is a better choice.
two :: Integer -> Integer
two i = round(2 ** fromIntegral(i))
This now works.

How can an arbitrary Num contain any other numeric type?

I'm just starting with Haskell, and I thought I'd start by making a random image generator. I looked around a bit and found JuicyPixels, which offers a neat function called generateImage. The example that they give doesn't seem to work out of the box.
Their example:
imageCreator :: String -> IO ()
imageCreator path = writePng path $ generateImage pixelRenderer 250 300
where pixelRenderer x y = PixelRGB8 x y 128
when I try this, I get that generateImage expects an Int -> Int -> PixelRGB8 whereas pixelRenderer is of type Pixel8 -> Pixel8 -> PixelRGB8. PixelRGB8 is of type Pixel8 -> Pixel8 -> Pixel8 -> PixelRGB8, so it makes sense that pixelRenderer is doing some type inference to determine that x and y are of type Pixel8. If I define a type signature that asserts that they are of type Int (so the function gets accepted by generateImage, PixelRGB8 complains that it needs Pixel8s, not Ints.
Pixel8 is just a type alias for Word8. After some hair pulling, I discovered that the way to convert an Int to a Word8 is by using fromIntegral.
The type signature for fromIntegral is (Integral a, Num b) => a -> b. It seems to me that the function doesn't actually know what you want to convert it to, so it converts to the very generic Num class. So theoretically, the output of this is a variable of any type that fits the type class Num (correct me if I'm mistaken here--as I understand it, classes are kind of like "interfaces" where types are more like classes/primitives in OOP). If I assign a variable
let n = fromIntegral 5
:t n -- n :: Num b => b
So I'm wondering... what is 'b'? I can use this variable as anything, and it will implicitly cast to any numeric type, as it seems. Not only will it implicitly cast to a Word8, it will implicitly cast to a Pixel8, meaning fromPixel effectively gets turned from (as I understood it) (Integral a, Num b) => a -> b to (Integral a) => a -> Pixel8 depending on context.
Can someone please clarify exactly what's happening here? Why can I use a generic Num as any type that fits Num, both mechanically and "ethically"? I don't understand how the implicit conversion is implemented (if I were to create my own class, I feel like I would need to add explicit conversion functions). I also don't really know why this works; here I can use a pretty unsafe type and convert it implicitly to anything else. (for example, fromIntegral 50000 gets translated to 80 if I implicitly convert it to a Word8)
A common implementation of type classes such as Num is dictionary-passing. Roughly, when the compiler sees something like
f :: Num a => a -> a
f x = x + 2
it transforms it into something like
f :: (Integer -> a, a -> a -> a) -> a -> a
-- ^-- the "dictionary"
f (dictFromInteger, dictPlus) x = dictPlus x (dictFromInteger 2)
The latter basically says: "pass me an implementation for these methods of class Num for your type a, and I will use them to produce a function a -> a for you".
Values such as your n :: Num b => b are no different. They are compiled into things such as
n :: (Integer -> b) -> b
n dictFromInteger = dictFromInteger 5 -- roughly
As you can see, this turns innocent-looking integer literals into functions, which can (and does) impact performance. However, in many circumstances the compiler can realize that the full polymorphic version is not actually needed, and remove all the dictionaries.
For instance, if you write f 3 but f expects Int, the "polymorphic" 3 can be converted at compile time. So type inference can aid the optimization phase (and user-written type annotation can greatly help here). Further, some other optimizations can be triggered manually, e.g. using the GHC SPECIALIZE pragma. Finally, the dreaded monomorphism restriction tries hard to force non-functions to remain non-functions after translation, at the cost of some loss of polymorphism. However, the MR is now being regarded as harmful, since it can cause puzzling type errors in some contexts.

Resources