Overloading function signatures haskell - haskell

I get the following error message when I compile:
Duplicate type signature:
weightedMedian.hs:71:0-39: findVal :: [ValPair] -> Double -> Double
weightedMedian.hs:68:0-36: findVal :: [ValPair] -> Int -> Double
My solution is to have findValI and findValD. However, findValI just converts the Int type to a Double and calls findValD.
Also I can't pattern match on types of Num (Int, Double) so I can't just change the type signature to
findVal :: [ValPair] -> Num -> Double
In many languages I wouldn't need different names. Why do I need different names in Haskell? Would this be hard to add to the language? Or are there dragons there?

Ad-hoc polymorphism (and name overloading) are provided in Haskell by typeclasses:
class CanFindVal a where
findVal :: [ValPair] -> a -> Double
instance CanFindVal Double where
findVal xs d = ...
instance CanFindVal Int where
findVal xs d = findVal xs (fromIntegral d :: Double)
Note that in this case, since findVal "really" needs a Double, I'd just always have it take a double, and when I needed to pass it an int, just use fromIntegral at the call site. You generally want typeclasses when there's actually different behavior or logic involved, rather than promiscuously.

Supporting both findVal :: [ValPair] -> Double -> Double and findVal :: [ValPair] -> Int -> Double requires ad-hoc polymorphism (see http://www.haskell.org/haskellwiki/Ad-hoc_polymorphism) which is generally dangerous. The reason is that ad-hoc polymorphism allows for changing semantics with the same syntax.
Haskell prefers what is called parametric polymorphism. You see this all the time with type signatures, where you have a type variable.
Haskell supports a safer version of ad-hoc polymorphism via type classes.
You have three options.
Continue what you are doing with an explicit function name. This is reasonable, it is even used by some c libraries, for example opengl.
Use a custom type class. This is probably the best way, but is heavy and requires a fair amount of code (by haskells very compact standards). Look at sclv's answer for code.
Try using an existing type class and (if you use GHC) get the performance with specializations.
Like this:
findVal :: Num a => [ValPair] -> a -> Double
{-# SPECIALISE findVal :: [ValPair] -> Int -> Double #-}
{-# SPECIALISE findVal :: [ValPair] -> Double -> Double #-}
findVal = ...

Haskell does not support C++-style overloading (well it sortof does with typeclasses, but we don't use them in the same way). And yeah there are some dragons associated to adding it, mostly having to do with type inference (becomes exponential time or undecidable or something like that). However, seeing "convenience" code like this is pretty uncommon in Haskell. Which one is it, an Int or a Double? Since your Int method delegates to the Double method, my guess is that Double is the "correct" one. Just use that one. Because of literal overloading, you can still call it as:
findVal whatever 42
And the 42 will be treated as a Double. The only case where this breaks is if you got something that is fundamentally an Int somewhere and you need need to pass it as this argument. Then use fromIntegral. But if you strive to have your code use the "correct" type everywhere, this case will be uncommon (and when you do have to convert, it will be worth drawing attention to that).

In this case, I think it's easy to write a function that handles both Int and Double for the second argument. Just write findVal so that is calls realToFrac on the second argument. That will convert the Int to a Double and just leave a Double alone. Then let the compiler deduce the type for you, if you are lazy.

In many other programming languages you can declare (sort of) functions having the same name but different other things in their signatures, such as different parameter types. That is called overloading and certainly is the most popular way to achieve ad-hoc polymorphism.
Haskell deliberately does NOT support overloading because it's designers don't consider it as the best way to achieve ad-hoc polymorphism. The Haskell way rather is constrained polymorphism and it involves declaring type classes and class instances

Related

The type-specification operator is like down-casting in Object-Oriented languages?

I was going through the book Haskell Programming from First Principles and came across following code-snippet.
Prelude> fifteen = 15
Prelude> :t fifteen
fifteen :: Num a => a
Prelude> fifteenInt = fifteen :: Int
Prelude> fifteenDouble = fifteen :: Double
Prelude> :t fifteenInt
fifteenInt :: Int
Prelude> :t fifteenDouble
fifteenInt :: Double
Here, Num is the type-class that is like the base class in OO languages. What I mean is when I write a polymorphic function, I take a type variable that is constrained by Num type class. However, as seen above, casting fifteen as Int or Double works. Isn't it equivalent to down-casting in OO languages?
Wouldn't some more information (a bunch of Double type specific functions in this case) be required for me to be able to do that?
Thanks for helping me out.
No, it's not equivalent. Downcasting in OO is a runtime operation: you have a value whose concrete type you don't know, and you basically assert that it has some particular case – which is an error if it happens to be actually a different concrete type.
In Haskell, :: isn't really an operator at all. It just adds extra information to the typechecker at compile-time. I.e. if it compiles at all, you can always be sure that it will actually work at runtime.
The reason it works at all is that fifteen has no concrete type. It's like a template / generic in OO languages. So when you add the :: Double constraint, the compiler can then pick what type is instantiated for a. And Double is ok because it is a member of the Num typeclass, but don't confuse a typeclass with an OO class: an OO class specifies one concrete type, which may however have subtypes. In Haskell, subtypes don't exist, and a class is more like an interface in OO languages. You can also think of a typeclass as a set of types, and fifteen has potentially all of the types in the Num class; which one of these is actually used can be chosen with a signature.
Downcasting is not a good analogy. Rather, compare to generic functions.
Very roughly, you can pretend that your fifteen is a generic function
// pseudo code in OOP
A fifteen<A>() where A : Num
When you use fifteen :: Double in Haskell, you tell the compiler that the result of the above function is Double, and that enables the compiler to "call" the above OOP function as fifteen<Double>(), inferring the generic argument.
With some extension on, GHC Haskell has a more direct way to choose the generic parameter, namely the type application fifteen #Double.
There is a difference between the two ways in that ... :: Double specifies what is the return type, while #Double specifies what is the generic argument. In this fifteen case they are the same, but this is not always the case. For instance:
> list = [(15, True)]
> :t list
list :: Num a => [(a, Bool)]
Here, to choose a = Double, we need to write either list :: [(Double, Bool)] or list #Double.
In the type forall a. Num a => a†, the forall a and Num a are parameters specified by the “caller”, that is, the place where the definition (fifteen) used. The type parameter is implicitly filled in with a type argument by GHC during type inference; the Num constraint becomes an extra parameter, a “dictionary” comprising a record of functions ((+), (-), abs, &c.) for a particular Num instance, and which Num dictionary to pass in is determined from the type. The type argument exists only at compile time, and the dictionary is then typically inlined to specialise the function and enable further optimisations, so neither of these parameters typically has any runtime representation.
So in fifteen :: Double, the compiler deduces that a must be equal to Double, giving (a ~ Double, Num a) => a, which is simplified first to Num Double => Double, then to simply Double, because the constraint Num Double is satisfied by the existence of an instance Num Double definition. There is no subtyping or runtime downcasting going on, only the solution of equality constraints, statically.
The type argument can also be specified explicitly with the TypeApplications syntax of fifteen #Double, typically written like fifteen<Double> in OO languages.
The inferred type of fifteen includes a Num constraint because the literal 15 is implicitly a call to something like fromInteger (15 :: Integer)‡. fromInteger has the type Num a => Integer -> a and is a method of the Num typeclass, so you can think of a literal as “partially applying” the Integer argument while leaving the Num a argument unspecified, then the caller decides which concrete type to supply for a, and the compiler inserts a call to the fromInteger function in the Num dictionary passed in for that type.
† forall quantifiers are typically implicit, but can be written explicitly with various extensions, such as ExplicitForAll, ScopedTypeVariables, and RankNTypes.
‡ I say “something like” because this abuses the notation 15 :: Integer to denote a literal Integer, not circularly defined in terms of fromInteger again. (Else it would loop: fromInteger 15 = fromInteger (fromInteger 15) = fromInteger (fromInteger (fromInteger 15))…) This desugaring can be “magic” because it’s a part of the language itself, not something defined within the language.

How does the :: operator syntax work in the context of bounded typeclass?

I'm learning Haskell and trying to understand the reasoning behind it's syntax design at the same time. Most of the syntax is beautiful.
But since :: normally is like a type annotation, How is it that this works:
Input: minBound::Int
Output: -2147483648
There is no separate operator: :: is a type annotation in that example. Perhaps the best way to understand this is to consider this code:
main = print (f minBound)
f :: Int -> Int
f = id
This also prints -2147483648. The use of minBound is inferred to be an Int because it is the parameter to f. Once the type has been inferred, the value for that type is known.
Now, back to:
main = print (minBound :: Int)
This works in the same way, except that minBound is known to be an Int because of the type annotation, rather than for some more complex reason. The :: isn't some binary operation; it just directs the compiler that the expression minBound has the type Int. Once again, since the type is known, the value can be determined from the type class.
:: still means "has type" in that example.
There are two ways you can use :: to write down type information. Type declarations, and inline type annotations. Presumably you've been used to seeing type declarations, as in:
plusOne :: Integer -> Integer
plusOne = (+1)
Here the plusOne :: Integer -> Integer line is a separate declaration about the identifier plusOne, informing the compiler what its type should be. It is then actually defined on the following line in another declaration.
The other way you can use :: is that you can embed type information in the middle of any expression. Any expression can be followed by :: and then a type, and it means the same thing as the expression on its own except with the additional constraint that it must have the given type. For example:
foo = ('a', 2) :: (Char, Integer)
bar = ('a', 2 :: Integer)
Note that for foo I attached the entire expression, so it is very little different from having used a separate foo :: (Char, Integer) declaration. bar is more interesting, since I gave a type annotation for just the 2 but used that within a larger expression (for the whole pair). 2 :: Integer is still an expression for the value 2; :: is not an operator that takes 2 as input and computes some result. Indeed if the 2 were already used in a context that requires it to be an Integer then the :: Integer annotation changes nothing at all. But because 2 is normally polymorphic in Haskell (it could fit into a context requiring an Integer, or a Double, or a Complex Float) the type annotation pins down that the type of this particular expression is Integer.
The use is that it avoids you having to restructure your code to have a separate declaration for the expression you want to attach a type to. To do that with my simple example would have required something like this:
two :: Integer
two = 2
baz = ('a', two)
Which adds a relatively large amount of extra code just to have something to attach :: Integer to. It also means when you're reading bar, you have to go read a whole separate definition to know what the second element of the pair is, instead of it being clearly stated right there.
So now we can answer your direct question. :: has no special or particular meaning with the Bounded type class or with minBound in particular. However it's useful with minBound (and other type class methods) because the whole point of type classes is to have overloaded names that do different things depending on the type. So selecting the type you want is useful!
minBound :: Int is just an expression using the value of minBound under the constraint that this particular time minBound is used as an Int, and so the value is -2147483648. As opposed to minBound :: Char which is '\NUL', or minBound :: Bool which is False.
None of those options mean anything different from using minBound where there was already some context requiring it to be an Int, or Char, or Bool; it's just a very quick and simple way of adding that context if there isn't one already.
It's worth being clear that both forms of :: are not operators as such. There's nothing terribly wrong with informally using the word operator for it, but be aware that "operator" has a specific meaning in Haskell; it refers to symbolic function names like +, *, &&, etc. Operators are first-class citizens of Haskell: we can bind them to variables1 and pass them around. For example I can do:
(|+|) = (+)
x = 1 |+| 2
But you cannot do this with ::. It is "hard-wired" into the language, just as the = symbol used for introducing definitions is, or the module Main ( main ) where syntax for module headers. As such there are lots of things that are true about Haskell operators that are not true about ::, so you need to be careful not to confuse yourself or others when you use the word "operator" informally to include ::.
1 Actually an operator is just a particular kind of variable name that is applied by writing it between two arguments instead of before them. The same function can be bound to operator and ordinary variables, even at the same time.
Just to add another example, with Monads you can play a little like this:
import Control.Monad
anyMonad :: (Monad m) => Int -> m Int
anyMonad x = (pure x) >>= (\x -> pure (x*x)) >>= (\x -> pure (x+2))
$> anyMonad 4 :: [Int]
=> [18]
$> anyMonad 4 :: Either a Int
=> Right 18
$> anyMonad 4 :: Maybe Int
=> Just 18
it's a generic example telling you that the functionality may change with the type, another example:

How to create a generic Complex type in haskell?

I want to create a Complex type to represent complex numbers.
Following works:
Prelude> data Complex = Complex Int Int
Prelude> :t Complex
Complex :: Int -> Int -> Complex
How can I change this to accept any Num type, instead of just Int.
I tried following:
Prelude> data Complex a = Num a => Complex a a
but got this:
* Data constructor `Complex' has existential type variables, a context, or a specialised result type
Complex :: forall a. Num a => a -> a -> Complex a
(Use ExistentialQuantification or GADTs to allow this)
* In the definition of data constructor `Complex'
In the data type declaration for `Complex'
I'm not really sure what to make of this error. Any help is appreciated.
Traditional data in Haskell is just that: data. It doesn't need to know anything about the properties of its fields, it just needs to be able to store them. Hence there's no real need to constrain the fields at that point; just make it
data Complex a = Complex !a !a
(! because strict fields are better for performance).
Of course when you then implement the Num instance, you will need a constraint:
instance (Num a) => Num (Complex a) where
fromInteger = (`Complex`0) . fromInteger
Complex r i + Complex ρ ι = Complex (r+ρ) (i+ι)
...
...in fact, you need the much stronger constraint RealFloat a to implement abs, at least that's how the standard version does it. (Which means, Complex Int is actually not usable, not with the standard Num hierarchy; you need e.g. Complex Double.)
That said, it is also possible to bake the constraint in to the data type itself. The ExistentialTypes syntax you tried is highly limiting though and not suitable for this; what you want instead is the GADT
data Complex a where
Complex :: Num a => a -> a -> Complex a
With that in place, you could then implement e.g. addition without mentioning any constraint in the signature
cplxAdd :: Complex a -> Complex a -> Complex a
cplxAdd (Complex r i) (Complex ρ ι) = Complex (r+ρ) (i+ι)
You would now need to fulfill Num whenever you try to construct a Complex value though. That means, you'd still need an explicit constraint in the Num instance.
Also, this version is potentially much slower, because the Num dictionary actually needs to be stored in the runtime representation.
Type constructors cannot be constrained in pure Haskell, only functions can. So it is supposed that you declare
data Complex a = Complex a a
and then constrain functions, like
conjugate :: (Num a) => Complex a -> Complex a
conjugate (Complex x y) = Complex x (-y)
In fact, the type and constraint for conjugate can be derived by the compiler, so you can just define the implementation:
conjugate (Complex x y) = Complex x (-y)
However, if you really wish to constrain the type constructor Complex, you can turn on some extensions that enable it, namely ExistentialQuantification or GADTs, as the compiler suggests. To do this, add this line to the very beginning of your file:
{-# LANGUAGE ExistentialQuantification #-}
or
{-# LANGUAGE GADTs #-}
Those are called pragmas.
While you could, as the compiler message instructs, use ExistentialQuantification, you could also define the type like this:
data Complex a = Complex a a deriving (Show, Eq)
It's a completely unconstrained type, so perhaps another name would be more appropriate... This type seems to often be called Pair...
When you write functions, however, you can constrain the values contained in the type:
myFunction :: Num a => Complex a -> a
myFunction (Complex x y) = x + y

Practical applications of Rank 2 polymorphism?

I'm covering polymorphism and I'm trying to see the practical uses of such a feature.
My basic understanding of Rank 2 is:
type MyType = ∀ a. a -> a
subFunction :: a -> a
subFunction el = el
mainFunction :: MyType -> Int
mainFunction func = func 3
I understand that this is allowing the user to use a polymorphic function (subFunction) inside mainFunction and strictly specify it's output (Int). This seems very similar to GADT's:
data Example a where
ExampleInt :: Int -> Example Int
ExampleBool :: Bool -> Example Bool
1) Given the above, is my understanding of Rank 2 polymorphism correct?
2) What are the general situations where Rank 2 polymorphism can be used, as opposed to GADT's, for example?
If you pass a polymorphic function as and argument to a Rank2-polymorphic function, you're essentially passing not just one function but a whole family of functions – for all possible types that fulfill the constraints.
Typically, those forall quantifiers come with a class constraint. For example, I might wish to do number arithmetic with two different types simultaneously (for comparing precision or whatever).
data FloatCompare = FloatCompare {
singlePrecision :: Float
, doublePrecision :: Double
}
Now I might want to modify those numbers through some maths operation. Something like
modifyFloat :: (Num -> Num) -> FloatCompare -> FloatCompare
But Num is not a type, only a type class. I could of course pass a function that would modify any particular number type, but I couldn't use that to modify both a Float and a Double value, at least not without some ugly (and possibly lossy) converting back and forth.
Solution: Rank-2 polymorphism!
modifyFloat :: (∀ n . Num n => n -> n) -> FloatCompare -> FloatCompare
mofidyFloat f (FloatCompare single double)
= FloatCompare (f single) (f double)
The best single example of how this is useful in practice are probably lenses. A lens is a “smart accessor function” to a field in some larger data structure. It allows you to access fields, update them, gather results... while at the same time composing in a very simple way. How it works: Rank2-polymorphism; every lens is polymorphic, with the different instantiations corresponding to the “getter” / “setter” aspects, respectively.
The go-to example of an application of rank-2 types is runST as Benjamin Hodgson mentioned in the comments. This is a rather good example and there are a variety of examples using the same trick. For example, branding to maintain abstract data type invariants across multiple types, avoiding confusion of differentials in ad, a region-based version of ST.
But I'd actually like to talk about how Haskell programmers are implicitly using rank-2 types all the time. Every type class whose methods have universally quantified types desugars to a dictionary with a field with a rank-2 type. In practice, this is virtually always a higher-kinded type class* like Functor or Monad. I'll use a simplified version of Alternative as an example. The class declaration is:
class Alternative f where
empty :: f a
(<|>) :: f a -> f a -> f a
The dictionary representing this class would be:
data AlternativeDict f = AlternativeDict {
empty :: forall a. f a,
(<|>) :: forall a. f a -> f a -> f a }
Sometimes such an encoding is nice as it allows one to use different "instances" for the same type, perhaps only locally. For example, Maybe has two obvious instances of Alternative depending on whether Just a <|> Just b is Just a or Just b. Languages without type classes, such as Scala, do indeed use this encoding.
To connect to leftaroundabout's reference to lenses, you can view the hierarchy there as a hierarchy of type classes and the lens combinators as simply tools for explicitly building the relevant type class dictionaries. Of course, the reason it isn't actually a hierarchy of type classes is that we usually will have multiple "instances" for the same type. E.g. _head and _head . _tail are both "instances" of Traversal' s a.
* A higher-kinded type class doesn't necessarily lead to this, and it can happen for a type class of kind *. For example:
-- Higher-kinded but doesn't require universal quantification.
class Sum c where
sum :: c Int -> Int
-- Not higher-kinded but does require universal quantification.
class Length l where
length :: [a] -> l
If you are using modules in Haskell, you are already using Rank-2 types. Theoretically speaking, modules are records with rank-2 type properties.
For example, the Foo module below in Haskell ...
module Foo(id) where
id :: forall a. a -> a
id x = x
import qualified Foo
main = do
putStrLn (Foo.id "hello")
return ()
... can actually be thought as a record as follows:
type FooType = FooType {
id :: forall a. a -> a
}
Foo :: FooType
Foo = Foo {
id = \x -> x
}
P/S (unrelated this question): from a language design perspective, if you are going to support module system, then you might as well support higher-rank types (i.e. allow arbitrary quantification of type variables on any level) to reduce duplication of efforts (i.e. type checking a module should be almost the same as type checking a record with higher rank types).

Type signature of num to double?

I'm just starting Learn You a Haskell for Great Good, and I'm having a bit of trouble with type classes. I would like to create a function that takes any number type and forces it to be a double.
My first thought was to define
numToDouble :: Num -> Double
But I don't think that worked because Num isn't a type, it's a typeclass (which seems to me to be a set of types). So looking at read, shows (Read a) => String -> a. I'm reading that as "read takes a string, and returns a thing of type a which is specified by the user". So I wrote the following
numToDouble :: (Num n) => n -> Double
numToDouble i = ((i) :: Double)
Which looks to me like "take thing of type n (must be in the Num typeclass, and convert it to a Double". This seems reasonable becuase I can do 20::Double
This produces the following output
Could not deduce (n ~ Double)
from the context (Num n)
bound by the type signature for numToDouble :: Num n => n -> Double
I have no idea what I'm reading. Based on what I can find, it seems like this has something to do with polymorphism?
Edit:
To be clear, my question is: Why isn't this working?
The reason you can say "20::Double" is that in Haskell an integer literal has type "Num a => a", meaning it can be any numeric type you like.
You are correct that a typeclass is a set of types. To be precise, it is the set of types that implement the functions in the "where" clause of the typeclass. Your type signature for your numToDouble correctly expresses what you want to do.
All you know about a value of type "n" in your function is that it implements the Num interface. This consists of +, -, *, negate, abs, signum and fromInteger. The last is the only one that does type conversion, but its not any use for what you want.
Bear in mind that Complex is also an instance of Num. What should numToDouble do with that? The Right Thing is not obvious, which is part of the reason you are having problems.
However lower down the type hierarchy you have the Real typeclass, which has instances for all the more straightforward numerical types you probably want to work with, like floats, doubles and the various types of integers. That includes a function "toRational" which converts any real value into a ratio, from which you can convert it to a Double using "fromRational", which is a function of the "Fractional" typeclass.
So try:
toDouble :: (Real n) => n -> Double
toDouble = fromRational . toRational
But of course this is actually too specific. GHCI says:
Prelude> :type fromRational . toRational
fromRational . toRational :: (Fractional c, Real a) => a -> c
So it converts any real type to any Fractional type (the latter covers anything that can do division, including things that are not instances of Real, like Complex) When messing around with numeric types I keep finding myself using it as a kind of generic numerical coercion.
Edit: as leftaroundabout says,
realToFrac = fromRational . toRational
You can't "convert" anything per se in Haskell. Between specific types, there may be the possibility to convert – with dedicated functions.
In your particular example, it certainly shouldn't work. Num is the class1 of all types that can be treated as numerical types, and that have numerical values in them (at least integer ones, so here's one such conversion function fromInteger).
But these types can apart from that have any other stuff in them, which oftentimes is not in the reals and can thus not be approximated by Double. The most obvious example is Complex.
The particular class that has only real numbers in it is, suprise, called Real. What is indeed a bit strange is that its method is a conversion toRational, since the rationals don't quite cover the reals... but they're dense within them, so it's kind of ok. At any rate, you can use that function to implement your desired conversion:
realToDouble :: Real n => n -> Double
realToDouble i = fromRational $ toRational i
Incidentally, that combination fromRational . toRational is already a standard function: realToFrac, a bit more general.
Calling type classes "sets of types" is kind of ok, much like you can often get away without calling any kind of collection in maths a set – but it's not really correct. The most problematic thing is, you can't really say some type is not in a particular class: type classes are open, so at any place in a project you could declare an instance for some type to a given class.
Just to be 100% clear, the problem is
(i) :: Double
This does not convert i to a Double, it demands that i already is a Double. That isn't what you mean at all.
The type signature for your function is correct. (Or at least, it means exactly what you think it means.) But your function's implementation is wrong.
If you want to convert one type of data to another, you have to actually call a function of some sort.
Unfortunately, Num itself only allows you to convert an Integer to any Num instance. You're trying to convert something that isn't necessarily an Integer, so this doesn't help. As others have said, you probably want fromRational or similar...
There is no such thing as numeric casts in Haskell. When you write i :: Double, what that means isn't "cast i to Double"; it's just an assertion that i's type is Double. In your case, however, your function's signature also asserts that i's type is Num n => n, i.e., any type n (chosen by the caller) that implements Num; so for example, n could be Integer. Those two assertions cannot be simultaneously true, hence you get an error.
The confusing thing is that you can say 1 :: Double. But that's because in Haskell, a numeric literal like 1 has the same meaning as fromInteger one, where one :: Integer is the Integer whose value is one.
But that only works for numeric literals. This is one of the surprising things if you come to Haskell from almost any other language. In most languages you can use expressions of mixed numeric types rather freely and rely on implicit coercions to "do what I mean"; in Haskell, on the other hand you have to use functions like fromIntegral or fromRational all the time. And while most statically typed languages have a syntax for casting from one numeric type to another, in Haskell you just use a function.

Resources