Function Definition in Haskell (GHCİ) - haskell

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.

Related

Arguments not needed when using foldl in haskell?

What I don't get is how it is possible to use foldl in this way in haskell. I do not understand how the argument ( in this case list) is carried over implicitly:
addAll :: [Int] -> Int
addAll = foldl (+) 0
-- This is how I could write foldl to simplify addAll where xs is clearly defined
addAll :: [Int] -> Int
addAll xs = foldl (+) 0 xs
or
addAll :: [Int] -> Int
addAll = \ xs -> foldl (+) 0 xs
But I don't really understand the first example. So basically I wonder how it is possible for something to be evaluated like that in haskell?
But I don't really understand the first example. So basically I wonder how it is possible for something to be evaluated like that in haskell?
The foldl (+) 0 produces a function. A function of type (Foldable f, Num a) => f a -> a, so why would you need an extra parameter? The addAll is a function as well.
In functional programming, functions are "first class citizens". This means that you can pass functions as parameters, and that the result can be a function. In Haskell every function takes exactly one parameter. Indeed:
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
is short for:
foldl :: Foldable t => (b -> a -> b) -> (b -> (t a -> b))
foldl is thus a function that takes as parameter a function of type (b -> a -> b), and produces a function of type b -> t a -> b. This thus means that foldl (+) has type:
foldl (+) :: (Foldable f, Num b) => b -> (f b -> b)
again a function that in this case takes a parameter the base case for foldl, and returns then a function that maps a (Foldable f, Num a) => f a -> f a. If you write foldl (+) 0, this is thus short for (fold (+)) 0.
Remember that all functions in Haskell are curried. foldl is no exception; it has type Foldable t => (b -> a -> b) -> b -> t a -> b, which means it takes an argument of type (b -> a -> b) and returns a function of type Foldable t => b -> t a -> b.
That function is also curried. foldl (+) takes an argument of type Int b => b and returns a function of type (Foldable t, Num b) => t b -> b.
Thus, foldl (+) 0 has type (Foldable t, Num b) => t b -> b, and your type annotation makes the restrictions t ~ [] and b ~ Int.

When does Haskell complain about incorrect typing in functions?

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 what condition we should use `[ ] a` in a type declaration?

I just see an expression
fmap_List :: (a -> b) -> [] a -> [] b
-- "[] a" means "[a]", for types.
fmap_List f [] = []
fmap_List f (x:xs) = f x : fmap_List f xs
Since [] a means [a], why we don't put [a] directly instead? Are there some special cases we should use [] a?
It’s just avoiding the syntactic sugar [a] as a way of illustrating that the f type parameter of fmap :: Functor f => (a -> b) -> f a -> f b is being replaced with the type constructor [], just like any other type constructor.
That is, you might write the type [a] as [] a when you want to emphasise the relationship to a signature that’s polymorphic over some type constructor, like fmap:
fmap :: Functor f => (a -> b) -> f a -> f b
-- f = []
fmap_List :: (a -> b) -> [] a -> [] b
fmap_List = fmap
-- f = Maybe
fmap_Maybe :: (a -> b) -> Maybe a -> Maybe b
fmap_Maybe = fmap
Or join:
join :: Monad m => m ( m a) -> m a
join_List :: [] ([] a) -> [] a
This is exactly the same as [[a]] -> [a], just making it clearer that m = [].
[] a is the type constructor [] applied to the type variable a. [] a or [a] has the kind *, the kind of types that are inhabited by values, such as Int, Char, Maybe Int, or Either String Int. [] has kind * -> *, the kind of types that take a type argument and produce a type as a result, such as [], Maybe, Identity, or Either e.
You can see this for example in the definition of instance Monad []—we’re giving the constructor [] (of kind * -> *) as an argument to Monad (of kind (* -> *) -> Constraint), not a type (of kind *) made with that constructor such as instance Monad ([] a). This is just like using Maybe instead of Maybe a, Maybe Int, Maybe String, &c.
Using the TypeApplications pragma, you can explicitly apply polymorphic functions to type arguments, e.g. in GHCi:
> :set -XTypeApplications
> :type fmap #[]
fmap #[] :: (a -> b) -> [a] -> [b]
> :type fmap #Maybe
fmap #Maybe :: (a -> b) -> Maybe a -> Maybe b
> :type fmap #[] #Int #Char
fmap #[] #Int #Char :: (Int -> Char) -> [Int] -> [Char]
> :type fmap #[] #_ #Bool
fmap #[] #_ #Bool :: (a -> Bool) -> [a] -> [Bool]
This is very useful for figuring out how to use polymorphic functions, or documenting which container or monad you’re using such a function with, by specialising a type to a (more) concrete instance:
> :type traverse
traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)
> :type traverse #[] #IO
traverse #[] #IO :: (a -> IO b) -> [a] -> IO [b]
And you can also ask GHCi for the kind of a type to get a better understanding of kinds:
> :kind Either
Either :: * -> * -> *
> :kind Either String
Either String :: * -> *
> :kind Either String Int
Either String Int :: *
> :kind []
[] :: * -> *
> :kind [] Int
[] Int :: *
> :kind [Int]
[Int] :: *
> :kind Functor
Functor :: (* -> *) -> Constraint
> :kind Num
Num :: * -> Constraint
The notation [] is useful when it is not being applied but passed to another type constructor.
Fix [] -- recursion-schemes
Free [] a -- free
ReaderT r [] a -- transformers
Compose [] Maybe a -- base (Data.Functor.Compose)
Since [] a means [a], why we don't put [a] directly instead?
This is a funny question. Let me try to convince you that, arguably, the real question is:
Since [a] means [] a, why we don't put [] a directly instead?
Consider the following parametric types:
data Identity a = Identity a
data Maybe a = Nothing | Just a
data HPair a = HPair a a
data HTriple a = HTriple a a a
data Tree a = Empty | Branch (Tree a) a (Tree a)
data List a = Nil | Cons a (List a)
data [a] = [] | (a : [a])
Note that all of these have the form TypeConstructor a, except for [a]! Indeed, to make the world more coherent, we should actually write [] a instead of [a].
This also makes it clear that [] is a type constructor, exactly like Identity, Maybe, Tree, ....
The syntax [a] is convenient, and possibly easier to read, especially for a beginner. However, it makes understanding the real nature of [] harder. Maybe has no such issue, by comparison.

Haskell foldr results in type error while foldl doesn't

I'm working through "Haskell Programming From First Principles". In the chapter on Folding Lists, exercise 5f,
when I evaluate
foldr const 'a' [1..5]
I get
No instance for (Num Char) arising from the literal ‘1’
However, with
foldl const 'a' [1..5]
I get 'a'.
I get that the folds are lazy, foldr doesn't traverse the spine and foldl does. But even looking at the definitions of foldr and foldl,
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
I can't figure out why it would have this type error. I'm guessing that the compiler is inferring type of x (Num) based on the type of z (Char), but I can't see where it draws the connection, since const or f doesn't require its two arguments to be the same type.
Any thoughts?
ok look at the type of foldr :: (a -> b -> b) -> b -> [a] -> b
Starting from the right you obviously must have a be some instance of Num and Enum (because you use [1..5])
Next you pass in 'a' so you have b ~ Char
Finally you have const for the function - and const is const :: a -> b -> a - note how you now must have a ~ b because you unify
a -> b -> b
a -> b -> a
^^^^^
but this of course would mean that 'a' must be a value of an instance of Num which Char is not ... there is your error (it's complaining about the 1 because starting left instead it's the point where the the problem becomes obvious)
foldl on the other side has foldl :: (b -> a -> b) -> b -> [a] -> b
so now you have again a some instance of Num, b must again be Char but now const just fits in (just switch b and a in the type of const)
foldl and foldr invoke f with a different order of arguments. That is foldr calls const x 'a', but foldl calls const 'a' x. The result of the latter is 'a', which is fine, but the result of the latter is x, which is wrong because x is an Int and the result is supposed to have the same type as the accumulator (Char).
This is a typing problem. The type of foldl is
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
and foldr type is:
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
When you apply foldr to const you get:
foldr const :: Foldable t => b -> t b -> b
Next, you supply 'a' argument, you get
(foldr const 'a') :: Foldable t => t Char -> Char
So, when you pass [1..5] as an argument it will try to unify t Char with (Enum a, Num a) => [a]. Type Char is an instance of Enum class but not Num and it is the reason why you get this error message.
As others have said, the order of arguments in a foldl and foldr are different. Use flip const instead:
> foldr (flip const) 'a' [1..5]
'a'

Having issues when making list an instance of a type class

I have made a type class and made list an instance of type class but I am getting an error which I do not understand
class MyType a where
listsum:: a->a->Double
instance (Num a)=>MyType [a] where
listsum x y = sum $ zipWith (-) x y
listsum returns a single value but this is the error I get:
Could not deduce (a ~ Double)
from the context (Num a)
bound by the instance declaration at b2.hs:4:10-28
`a' is a rigid type variable bound by
the instance declaration at b2.hs:4:10
In the expression: sum $ zipWith (-) x y
In an equation for `listsum': listsum x y = sum $ zipWith (-) x y
In the instance declaration for `MyType [a]'
Failed, modules loaded: none.
How do I solve this?
Let's write down some annotations.
sum :: (Num a, Foldable t) => t a -> a
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
(-) :: Num a => a -> a -> a
Let's derive the type of \ x y -> sum $ zipWith (-) x y.
-- 1. Let's substitute (-) to zipWith:
zipWith (-) :: Num a => [a] -> [a] -> [a]
-- 2. Let's substitute `(zipWith (-))` to `sum`. We can't
-- write it point free like in `zipWith (-)` case. So we add
-- two extra params:
(\ x y -> sum $ zipWith (-) x y) :: Num a => [a] -> [a] -> a
The type of listsum for [a] is:
listsum :: (Num a) => [a] -> [a] -> Double
It takes two lists of something of (Num a => a) and
returns Double. But (\ x y -> sum $ zipWith (-) x y)
returns any (Num a => a). The compiler cannot be sure
that this (Num a => a) will always be Double. That's why you
get the error:
Could not deduce (a ~ Double) from the context (Num a)
#sclv gave you two options to solve it. Another one is
to change the MyType class to
class MyType a where
listsum:: [a] -> [a] -> a
so that the listsum and (\ x y -> sum $ zipWith (-) x y) has the same type.
It also gives you an opportunity to parametrize listsum by a type of elements of list.
You can modify listsum:: a -> a -> Double to be listsum :: [a] -> [a] -> a and declare your instance over a rather than [a] Or you can modify your instance from instance (Num a) => MyType [a] to instance MyType [Double].
You can see the error by just taking the type of the expression \x y -> sum $ zipWith (-) x y. You will see that it is Num a => [a] -> [a] -> a and not Num a => [a] -> [a] -> Double as your class currently requires.

Resources