I have managed to implement a mock filter functions (after lots of attempts)
filter' :: (Num a, Eq a) => (a -> Bool) -> [a] -> [a]
filter' a [] = []
filter' a (x:xs) = if a x
then x : filter' a xs
else filter' a xs
What I don't clearly understand is the type declaration
filter' :: (Num a, Eq a) => (a -> Bool) -> [a] -> [a]
-- filter' (<10) [1,2,3]
-- output = []
We pass in (<10) [1,2,3]. However in the type declaration (a -> Bool) we pass in a which comes from the list recursively and the output is either true or false. However what about the expressing the test (<10)? Why don't we add another Bool?
The type of your filter' function is only so constrained because you've declared that it is. If you don't declare the type, the compiler will infer a more tolerant type: (a -> Bool) -> [a] -> [a]. This is the same type as the built-in filter function:
Prelude> :type filter
filter :: (a -> Bool) -> [a] -> [a]
The expression (< 10) is a so-called section. It's a partially applied function.
The operator < is itself a function:
Prelude> :type (<)
(<) :: Ord a => a -> a -> Bool
You can read this as: < is a function that takes two arguments, both of the generic type a. The type a must belong to the typeclass Ord. When you call < with such two values, a Bool value is returned.
Since Haskell functions are curried, you can call a function with only some of the arguments. The return value is a new function that 'waits for the remaining arguments':
Prelude> :type (< 10)
(< 10) :: (Num a, Ord a) => a -> Bool
This type is a little more constrained, because the literal 10 is inferred to belong to the Num typeclass. Since < is in use, the original constraint for that (Ord) is still in effect as well.
The expression [1,2,3] is is by the compiler inferred as:
Prelude> :type [1,2,3]
[1,2,3] :: Num t => [t]
The values all belong to the Num typeclass. When you use all of these types together, you get the union of all the inferred types:
Prelude> :type filter (< 10) [1,2,3]
filter (< 10) [1,2,3] :: (Num a, Ord a) => [a]
The Num typeclass is inferred because of the use of literals, and the Ord typeclass is inferred because of the use of the < operator.
Related
I am a Haskell newbie trying to wrap my head around type binding in functions and how Haskell enforces it. For example, even though the type for the fst function is fst :: (a, b) -> a, the compiler does not complain for the function fst'. But the compiler complains about type bindings for the function elem'.
fst' :: (a,a) -> a
fst' s = fst s
elem' :: (Eq a, Eq b) => a -> [b] -> Bool
elem' x xs = elem x xs
fst has as type fst :: (a, b) -> a so that means it is fine to define a function:
fst' :: (a, a) -> a
fst' = fst
Your fst' function is more restrictive than the fst function. Regardless with what you replace a in your fst' function that is fine for fst. If for example a ~ Bool holds, then you call fst with signature fst :: (Bool, Bool) -> Bool. But since fst can deal with all as and b, it is fine that both elements of the tuple are Bool, so given fst can handle tuples for all possible types for both the first and the second item of the 2-tuple, it is defintely ok if the two items have the same type.
The latter is not ok, here you define:
elem' :: (Eq a, Eq b) => a -> [b] -> Bool
elem' = elem
but elem has type elem :: Eq a => a -> [a] -> Bool. The signatures you can make with the elem' function are not a subset of the ones of the elem function, since you can set a ~ Int and b ~ Bool. In that case you expect elem :: Int -> [Bool] -> Bool, but evidently that does not hold, since the Int and Bool type are two different types, and in the elem signature, these are both as.
In GHCi, doing the following yield:
:t (==)
(==) :: Eq a => a -> a -> Bool
or
:t elem
elem :: (Eq a, Foldable t) => a -> t a -> Bool
I am confused with the arrow going from a to a, and then a to Bool.
Is it because == or elem is a curried function?
The type signature for elem is very similar to ==, except for the additional t. What does t a in :t elem mean?
Yes, operators are curried. Let's ignore the contexts for a second (the part of the type before =>).
(==) :: a -> a -> Bool
(->) associates to the right, so this means:
(==) :: a -> (a -> Bool)
That is, it's a function which, given an a, returns another function, which in turn takes an a and gives a Bool. It returns the function which is only true when its argument is equal to the first a.
(We will set NoMonomorphismRestriction because otherwise it will just be extra confusing for no good reason)
ghci> :set -XNoMonomorphismRestriction
ghci> let f = (==) 1
ghci> f 1
True
ghci> f 2
False
-- or just
ghci> (==) 1 2
False
The part before the (=>) puts constraints on types. Eq a means that a must be a type that supports equality.
As for the t in elem, that might be a bit advanced for you to understand fully right now. I'll give you a little bit. Because of the context
(Eq a, Foldable t) => ...
we know that t has to be Foldable. Lists are foldable, and foldable doesn't mean much more than "has a toList method". So you can read elem as:
elem :: (Eq a) => a -> [a] -> Bool
and in general, when you see a foldable type, just pretend it's a list.
take' :: (Num i, Ord i) => i -> [a] -> [a]
(Num i , Ord i) means class constraint
i -> [a] means this two is belong to class constraint
last [a] mean's output.
is it correct?
It's a little difficult to understand what you're asking. If you just want to know what the type signature means, you can break it down as:
take' :: (Num i, Ord i) => i -> [a] -> [a]
-- ^--- The function named "take'"
take' :: (Num i, Ord i) => i -> [a] -> [a]
-- ^--- Has type
take' :: (Num i, Ord i) => i -> [a] -> [a]
-- ^--- Constrained where "i" implements "Num" and "Ord"
take' :: (Num i, Ord i) => i -> [a] -> [a]
-- ^--- The first argument has type "i"
take' :: (Num i, Ord i) => i -> [a] -> [a]
-- ^--- The second argument has type "[a]"
take' :: (Num i, Ord i) => i -> [a] -> [a]
-- The return value has type "[a]" ---^
So in one sentence, the function take' has two arguments, the first argument must be a Num and an Ord, the second argument must be a list of any type, and the return value has the same type as the second argument.
Without knowing the implementation I can only comment on the type signature.
Constraint part you got right. It's a type class constraints where i must have a Num and Ord instance.
(Num i , Ord i) =>
The second part is a a function of two variables from an ordered numeric value i to a list of polymorphic types of a to a list of the same type a.
i -> [a] -> [a]
An implementation of this function might look like:
take' :: (Num i, Ord i) => i -> [a] -> [a]
take' n _ | n <= 0 = []
take' _ [] = []
take' n (x:xs) = x : take' (n-1) xs
(Num i, Ord i) means that everywhere in the type signature of the function i is a member of the Num class and the Ord class. These are, rather obviously, short for number and order. Here are their definitions.
class Num a where
(+), (*), (-) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
class Eq a => Ord a where
compare :: a -> a -> Ordering
(<) :: a -> a -> Bool
(>=) :: a -> a -> Bool
(>) :: a -> a -> Bool
(<=) :: a -> a -> Bool
max :: a -> a -> a
min :: a -> a -> a
So what does this all mean. Well, it means for every type that is an instance of this class the following functions can be used with that type. For the Num class these are basic operations that you would expect to be able to apply to a number. Notice the lack of division. Because Int and Integer are a type of Num there is no division because if you divide by something that is not divisible then you end up with a non integral type. This is why there are more type classes to handle this, such as Fractional.
The Ord class provides functions for ordering values of certain types. This allows people to compare values and form some sort of logical ordering of values.
The type signature chosen is a bit strange though as I would think
take' :: Integral i => i -> [a] -> [a]
Would make more sense.
I've just started programming in Haskell, and I am solving 99 Haskell problems, and when I was nearly done with 10th, I've encountered this problem:
-- Exercise 9
pack :: Eq a => [a] -> [[a]]
pack [] = []
pack list = let (left,right) = span (== head list) list in
left : pack right
-- Exercise 10
encode :: (Eq a, Integral c) => [a] -> [(c, a)]
encode [] = []
encode list = map (\x -> (length x, head x)) (pack list)
-- this doesn't work ^^^^^^^^
The error produced told me that
Could not deduce (c ~ Int)
from the context (Eq a, Integral c)
bound by the type signature for
encode :: (Eq a, Integral c) => [a] -> [(c, a)]
at C:\fakepath\ex.hs:6:11-47
`c' is a rigid type variable bound by
the type signature for
encode :: (Eq a, Integral c) => [a] -> [(c, a)]
at C:\fakepath\ex.hs:6:11
In the return type of a call of `length'
In the expression: length x
In the expression: (length x, head x)
I've managed to fix that by inserting a function I've read about in Learn you a Haskell: fromIntegral.
encode list = map (\x -> (fromIntegral $ length x, head x)) (pack list)
So, my question is, why is that needed?
I've run :t length and got [a] -> Int, which is a pretty defined type for me, which should satisfy Integral c constraint.
The type signature (Eq a, Integral c) => [a] -> [(c, a)] means the function works for any types a and c in the appropriate typeclasses. The actual type used is specified at the call site.
As a simple example, let's take a look at the type of the empty list:
:t []
[a]
What this means is that [] represents an empty list of String, and empty list of Int, an empty list of Maybe [Maybe Bool] and whatever other types you can imagine. We can imagine wrapping this in a normal identifier:
empty :: [a]
empty = []
empty obviously works the same way as []. So you can see that the following definition would make no sense:
empty :: [a]
empty = [True]
after all, [True] can never be a [Int] or [String] or whatever other empty list you want.
The idea here is the same, except we have typeclass constraints on the variables as well. For example, you can use encode to return a [(Integer, String)] list because Integer is also in the Integral class.
So you have to return something polymorphic that could be any Integral--just what fromIntegral does. If you just returned Int, encode would only be usable as an Int and not any Integral.
I am a beginner of Haskell. What is wrong with this expression?:
Prelude> let { f op [] = [] ; f op (h:t) = op h : f op t }
Prelude> f (+) []
<interactive>:337:1:
No instance for (Show (t0 -> t0))
arising from a use of `print'
Possible fix: add an instance declaration for (Show (t0 -> t0))
In a stmt of an interactive GHCi command: print it
Many thanks for support.
Function (+) has type (+) :: Num a => a -> a -> a and function f has type f :: (t -> a) -> [t] -> [a].
f expects a function of one argument.
f (+1) [] will be correct
Your function is inferred to have this type: (x -> y) -> [x] -> [y].
(+) has type Num a => a -> a -> a. This can be an instance of the type (x -> y) if we take x to be a and y to be a -> a, so all is fine. So the empty list in f (+) [] must be of type [a], and the return type must be [a -> a] (all of this with the same Num a constraint, of course). So f (+) [] correctly computes an empty list of type Num a => [a -> a].
This is all fine, but then GHCi wants to print the result of your expression. There is no way of printing values of type Num a => [a -> a], because there is no way to print functions. This is basically the error GHCi is giving you: No instance for (Show (t0 -> t0)).
There's nothing actually wrong with your function, or with your invocation of that function. It's just that it results in an (empty) list of functions, which you can't print. If you'd let bound it instead, you wouldn't get an error, and you could go on to do with it anything you would normally expect to be able to do with a Num a => [a -> a].
The type of the function f is:
Prelude> :t f
f :: (t -> a) -> [t] -> [a]
If you call the function like this:
Prelude> f (+) []
... you get the types (Let's pretend that (+) only works for Ints in this example):
(+) :: Int -> Int -> Int
(t -> a) = (Int -> (Int -> Int))
t = Int
a = (Int -> Int)
This means that the second argument to f is of type [t] = [Int] and the return type is [a] = [Int -> Int]. Because the return type is a list of functions, and functions cannot be shown, ghci will refuse to "compile" the expression because of the type errors, and you get the error that you see.
The f (+) [] function returns a list of functions:
Prelude> :t f (+) []
f (+) [] :: Num t => [t -> t]
And prelude trying to call show function on each element of the resulting list, however functions are not instances of the Show type class.