Basic Haskell function types? - haskell

Super basic question - but I can't seem to get a clear answer. The below function won't compile:
randomfunc :: a -> a -> b
randomfunc e1 e2
| e1 > 2 && e2 > 2 = "Both greater"
| otherwise = "Not both greater"
main = do
let x = randomfunc 2 1
putStrLn $ show x
I'm confused as to why this won't work. Both parameters are type 'a' (Ints) and the return parameter is type 'b' (String)?
Error:
"Couldn't match expected type ‘b’ with actual type ‘[Char]’"

Not quite. Your function signature indicates: for all types a and b, randomfunc will return something of type b if given two things of type a.
However, randomFunc returns a String ([Char]). And since you compare e1 with 2 each other, you cannot use all a's, only those that can be used with >:
(>) :: Ord a => a -> a -> Bool
Note that e1 > 2 also needs a way to create such an an a from 2:
(> 2) :: (Num a, Ord a) => a -> Bool
So either use a specific type, or make sure that you handle all those constraints correctly:
randomfunc :: Int -> Int -> String
randomFunc :: (Ord a, Num a) => a -> a -> String

Both parameters are type 'a' (Ints) and the return parameter is type 'b' (String)?
In a Haskell type signature, when you write names that begin with a lowercase letter such as a, the compiler implicitly adds forall a. to the beginning of the type. So, this is what the compiler actually sees:
randomfunc :: forall a b. a -> a -> b
The type signature claims that your function will work for whatever ("for all") types a and b the caller throws at you. But this is not true for your function, since it only works on Int and String respectively.
You need to make your type more specific:
randomfunc :: Int -> Int -> String
On the other hand, perhaps you intended to ask the compiler to fill out a and b for you automatically, rather than to claim that it will work for all a and b. In that case, what you are really looking for is the PartialTypeSignatures feature:
{-# LANGUAGE PartialTypeSignatures #-}
randomfunc :: _a -> _a -> _b

Related

Haskell defined types

Studying Haskell first principles. Absolute beginner in Haskell.
If:
data A
data B
func :: A -> B
func = undefined
What would the actual function be? Worked though load of exercises with great result (also thanks to you) but again I am stuck. Does A -> B indicate two different types like 'String' -> 'Char'? Just trying to wrap my head around it.
No, (concrete) types start with an Uppercase. So A -> B means the types A and B you have defined (well not defined here) with your data A = ... expressions, like for instance:
data A = Foo | Bar Int | Qux String A
In case the signature contains an identifier with a lowercase, it is a type variable. For instance foo :: a -> b, means a and b can be substuted by any type. So foo is a function that can be A -> B, but also A -> Int, Char -> B, and Char -> Int.
You can also add type constraints to the signature to restrict the types for which for instance a and b can be used. Like foo :: (Show a, Num b) => a -> b restricts a and b, such that there should exist an instance Show a and instance Num b for the types a and b such that foo is defined over these types.
Thanks Willem, Chepner. Your answers helped me out to conjure up:
data A
data B
funcAJ :: A -> B
funcAJ a = a
where a = b
b = undefined
This typechecks as funcAJ :: A -> B, which I understand. Thanks so much!

inferred type of function in Haskell

I defined a function as follows in Haskell
func x | x > 0 = 4
| otherwise = error "Non positive number"
Its inferred type is
func :: (Ord a, Num a, Num t) => a -> t
Why can't its type be
func :: (Ord a, Num a) => a -> a
The type func :: (Ord a, Num a) => a -> a means that returned type should match with one you passed in. But since you are returning a constant and it doesn't depend on input, its type can be any type of class Num. Thus, compiler infers func :: (Ord a, Num a, Num t) => a -> t.
The inferred type is correct. Let's see how it gets inferred. We will only look at the returned value first:
func x | … = 4
| … = error "…"
The latter term, error "…" :: a, is unconstrained. However, 4 has the type Num a => a, therefore your function will have type
func :: (Num result) => ????? -> result
Now let's have a look at x:
func x | x > 0 = …
| …
Due to the use of (>) :: Ord a => a -> a- > Bool and 0 :: Num a, x's has to be an instance of both Num and Ord. So from that point of perspective, we have
func :: (Num a, Ord a) => a -> ????
The important part is that 4 and x don't interact. Therefore func has
func :: (Num a, Ord a, Num result) => a -> result
Of course, result and a could be the same type. By the way, as soon as you connect x and 4, the type will get more specific:
func x | x > 0 = 4 + x - x
| …
will have type (Num a, Ord a) => a -> a.
As you may or may not be aware, Haskell’s numeric literals are polymorphic. That means that a number literal, like 0 or 4, has the type Num a => a. You seem to already understand this, since the type signature you expect includes a Num constraint.
And indeed, the type signature you have provided is a valid one. If you included it, it would be accepted by the compiler, and if it’s the type you actually want, by all means include it. However, the reason it is different from the inferred type is that Haskell will attempt to infer the most general type possible, and the inferred type is more general than the one you’ve written.
The question is, why is the inferred type permitted? Well, consider this similar but distinct function:
func' x | x > 0 = "ok"
| otherwise = error "Non positive number"
This function’s type is (Ord a, Num a) => a -> String. Notably, the input of the function has absolutely no bearing on the output, aside from whether or not the result is ⊥. For this reason, the result can be absolutely anything, including a string.
However, consider yet another function, again similar but distinct:
func'' x | x > 0 = x - 1
| otherwise = error "Non positive number"
This function must have the type you described, since it uses x to produce a new value.
However, look again at the original func definition. Note how the literal on the right hand side, the 4, does not have anything to do with x. That definition is actually quite a bit closer to func' than func'', so the numeric literal has the type Num t => t, and it never needs to be specialized. Therefore, the inferred type allows the two numeric types to be separate, and you have the more general type written in your question.

Function with type a -> b in Haskell?

Is there any kind of function in Haskell that has type a -> b? That means, is it possible to write a function such that f :: a -> b? I don't think a function like that exists for the following reason: suppose that we found f where f :: a -> b, what would f 2 produce? a value of type b, but what is b since Haskell cannot infere (I think) it from the arguments I gave? Is this correct? Otherwise, can you give me an example of such a function?
Barring ⊥ (bottom value – undefined etc.), which is always possible but never useful, there can indeed be no such function. This is one of the simplest instances of the so-called free theorems that we get from polymorphic type signatures.
You're on the right track with your intuitive explanation of why this is not possible, though it went off in the end. Yes, you can consider f (5 :: Int). The problem is not that the compiler “can't infer” what b would be – that would be the case for many realistic functions, e.g.
fromIntegral :: (Num b, Integral a) => a -> b
makes perfect sense; b will be inferred from the environment in which fromIntegral x is used. For instance, I might write†
average :: [Double] -> Double
average l = sum l / fromIntegral (length l)
In this case, length l :: a has the fixed type Int and fromIntegral (length l) :: b must have the fixed type Double to fit in the environment, and unlike in most other languages with type inference, information from the environment is available hereto in a Hindley-Milner based language.
No, the problem with f :: a -> b is that you could instantiate a and b to any ridiculous combination of types, not just different number types. Because f is unconstrainedly polymorphic, it would have to be able to convert any type into any other type.
In particular, it would be able to convert into the vacuous type Void.
evil :: Int -> Void
evil = f
And then I could have
muahar :: Void
muahar = f 0
But, by construction of Void, there cannot be a value of this type (save for ⊥ which you can't evaluate without either crashing or looping infinitely).
†It should be noted that this is by some standards not a very good way of computing the average.
In order to implement f :: a -> b, it means that f has to be able to return any possible type. Even types that don't exist today, but somebody could define in ten years' time. Without some kind of reflection feature, that's obviously impossible.
Well... "impossible" is a big word... As the other answers point out, it's impossible excluding bottom. In other words, f can never return a value of type b. It can throw an exception, or loop forever. But (arguably) neither of those things is really "returning a value".
f1 :: a -> b
f1 = error "f1"
f2 :: a -> b
f2 s = error "f2"
f3 :: a -> b
f3 x = f3 x
These functions are all subtly different, and they all compile just fine. And, of course, they're all useless! So yes, there is no useful function with type a -> b.
If you want to split hairs:
f1 throws an exception.
f1 'x' throws an exception.
f2 is a normal-looking function.
f2 'x' throws an exception.
f3 is a normal-looking function.
f3 'x' doesn't throw an exception, but it loops forever, so it never actually returns anything.
Basically any function you see that returns "any type" is a function that never actually returns. We can see this in unusual monads. For example:
f4 :: a -> Maybe b
It is perfectly possible to implement this function without throwing an exception or looping forever.
f4 x = Nothing
Again, we're not actually returning a b. We could similarly do
f5 :: a -> [b]
f5 x = []
f6 :: a -> Either String b
f6 x = Left "Not here"
f7 :: a -> Parser b
f7 x = fail "Not here"
There is, I think, exactly one, but it is cheating a little bit:
> let f _ = undefined
> :t f
f:: t -> t1
This only exists because bottom is considered a value of every type.
... but what is b since Haskell cannot infer it from the arguments I gave?
Depending on the context, Haskell can infer the return type; say:
{-# LANGUAGE MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances #-}
class Cast a b where
cast :: a -> b
instance Cast a a where
cast = id
instance Cast Int String where
cast = show
instance Cast Int Double where
cast = fromIntegral
then,
cast :: Cast a b => a -> b
and if given enough context, Haskell knows which function to use:
\> let a = 42 :: Int
\> let b = 100.0 :: Double
\> "string: " ++ cast a -- Int -> String
"string: 42"
\> b * cast a -- Int -> Double
4200.0

Determining the type of a function

I am trying to figure out the way Haskell determines type of a function. I wrote a sample code:
compareAndIncrease a b =
if a > b then a+1:b:[]
else a:b:[]
which constructs a list basing on the a > b comparison. Then i checked its type with :t command:
compareAndIncrease :: (Ord a, Num a) => a -> a -> [a]
OK, so I need a typeclass Ord for comparison, Num for numerical computations (like a+1). Then I take parameters a and b and get a list in return (a->a->[a]). Everything seems fine. But then I found somewhere a function to replicate the number:
replicate' a b
| a ==0 = []
| a>0 = b:replicate(a-1) b
Note that normal, library replicate function is used inside, not the replicate' one. It should be similar to compareAndIncrease, because it uses comparison, numerical operations and returns a list, so I thought it would work like this:
replicate' :: (Ord a, Num a) => a -> a -> [a]
However, when I checked with :t, I got this result:
replicate' :: Int -> t -> [t]
I continued fiddling with this function and changed it's name to repval, so now it is:
Could anyone explain to me what is happening?
GHCi is a great tool to use here:
*Main> :type replicate
replicate :: Int -> a -> [a]
You define replicate' in terms of replicate (I rename your variables for clarity):
replicate' n e
| -- blah blah blah
| n > 0 = e : replicate (n - 1) e
Since you call replicate (n - 1), the type checker infers that n - 1 must have type Int, from which it infers that n must have type Int, from which it infers that replicate' has type Int -> a -> [a].
If you wrote your replicate' recursively, using replicate' inside instead of replicate, then you would get
*Main> :type replicate'
replicate' :: (Ord a, Num a) => a -> a1 -> [a1]
Edit
As Ganesh Sittampalam points out, it's best to constrain the type to Integral as it doesn't really make sense to replicate a fractional number of times.
The key flaw in your reasoning is that replicate actually only takes Int for the replication count, rather than a more general numeric type.
If you instead used genericReplicate, then your argument would be roughly valid.
genericReplicate :: Integral i => i -> a -> [a]
However note that the constraint is Integral rather than Num because Num covers any kind of number including real numbers, whereas it only makes sense to repeat something an integer number of times.

Haskell type declarations

In Haskell, why does this compile:
splice :: String -> String -> String
splice a b = a ++ b
main = print (splice "hi" "ya")
but this does not:
splice :: (String a) => a -> a -> a
splice a b = a ++ b
main = print (splice "hi" "ya")
>> Type constructor `String' used as a class
I would have thought these were the same thing. Is there a way to use the second style, which avoids repeating the type name 3 times?
The => syntax in types is for typeclasses.
When you say f :: (Something a) => a, you aren't saying that a is a Something, you're saying that it is a type "in the group of" Something types.
For example, Num is a typeclass, which includes such types as Int and Float.
Still, there is no type Num, so I can't say
f :: Num -> Num
f x = x + 5
However, I could either say
f :: Int -> Int
f x = x + 5
or
f :: (Num a) => a -> a
f x = x + 5
Actually, it is possible:
Prelude> :set -XTypeFamilies
Prelude> let splice :: (a~String) => a->a->a; splice a b = a++b
Prelude> :t splice
splice :: String -> String -> String
This uses the equational constraint ~. But I'd avoid that, it's not really much shorter than simply writing String -> String -> String, rather harder to understand, and more difficult for the compiler to resolve.
Is there a way to use the second style, which avoids repeating the type name 3 times?
For simplifying type signatures, you may use type synonyms. For example you could write
type S = String
splice :: S -> S -> S
or something like
type BinOp a = a -> a -> a
splice :: BinOp String
however, for something as simple as String -> String -> String, I recommend just typing it out. Type synonyms should be used to make type signatures more readable, not less.
In this particular case, you could also generalize your type signature to
splice :: [a] -> [a] -> [a]
since it doesn't depend on the elements being characters at all.
Well... String is a type, and you were trying to use it as a class.
If you want an example of a polymorphic version of your splice function, try:
import Data.Monoid
splice :: Monoid a=> a -> a -> a
splice = mappend
EDIT: so the syntax here is that Uppercase words appearing left of => are type classes constraining variables that appear to the right of =>. All the Uppercase words to the right are names of types
You might find explanations in this Learn You a Haskell chapter handy.

Resources