Equivalent functions producing different interpreter results - haskell

Background: I'm investigating anonymous recursion, and I'm taking on the challenge of implementing the prelude without using any named recursion just to help it all sit nicely in my mind. I'm not quite there yet, and along the way I've run into something unrelated but still interesting.
map1 = \f -> \x -> if (tail x) == []
then [f (head x)]
else f (head x) : (map1 f (tail x))
map2 f x = if (tail x) == []
then [f (head x)]
else f (head x) : (map2 f (tail x))
map3 f (x:xs) = if xs == [] then [f x] else f x : (map3 f xs)
map4 f (x:[]) = [f x]
map4 f (x:xs) = f x : map4 f xs
GHC complains about the first one, is fine with the second and the third and fourth ones are there just to show how they could be implemented differently.
*Main> map1 (*2) [1..10]
<interactive>:1:15:
No instance for (Num ())
arising from the literal `10'
Possible fix: add an instance declaration for (Num ())
In the expression: 10
In the second argument of `map1', namely `[1 .. 10]'
In the expression: map1 (* 2) [1 .. 10]
*Main> map2 (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
*Main> map3 (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
*Main> map4 (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
If I add a type signature to map1 it's all good.
map1 :: Eq a => (a -> b) -> [a] -> [b]
The first two functions seem pretty much the same to me, so I suppose my question is simply "What's going on here?"

You were bitten by the monomorphism restriction. Anything that is written as foo = ... - meaning that there are no arguments to the definition, and no explicit type is given - has to have a non-generic type according to this restriction. The generic type in this case would, as you said, have had to be Eq a => (a -> b) -> [a] -> [b], but since the monomorphism restriction applies, both a and b are replaced by (), the simplest type that can be inferred for the available type variables.

But, if you use the unconstrained null instead of (== []),
Prelude> let map0 = \f -> \x -> if null (tail x) then [f (head x)] else f (head x) : map0 f (tail x)
Prelude> :t map0
map0 :: (a -> t) -> [a] -> [t]
Prelude> map (*2) [1 .. 10]
[2,4,6,8,10,12,14,16,18,20]
it works without arguments or a signature. Only constrained type variables are subject to the monomorphism restriction.
And if you put the definition of map1 into a file and try to compile it or load it into ghci,
Ambiguous type variable `a0' in the constraint:
(Eq a0) arising from a use of `=='
Possible cause: the monomorphism restriction applied to the following:
map1 :: forall t. (a0 -> t) -> [a0] -> [t] (bound at Maps.hs:3:1)
Probable fix: give these definition(s) an explicit type signature
or use -XNoMonomorphismRestriction
In the expression: (tail x) == []
In the expression:
if (tail x) == [] then
[f (head x)]
else
f (head x) : (map1 f (tail x))
In the expression:
\ x
-> if (tail x) == [] then
[f (head x)]
else
f (head x) : (map1 f (tail x))
ghci only complained in the way it did because it uses ExtendedDefaultRules, otherwise you would have gotten an understandable error message.

Related

Can not lift multiple parameters in a monad

Hello i am trying to do the following:
module MyMonad where
f::(Monad m),=>m (a->b->c)->m a -> m b -> m c
f mf ma mb=
ma >>= \a ->
mb >>= \b ->
mf >>= \c ->
return (c a b)
and use it like this :
f (Just 3) (Just 4)
And i get the following error:
* Non type-variable argument in the constraint: Num (a -> b -> c)
(Use FlexibleContexts to permit this)
* When checking the inferred type
it :: forall a b c.
(Num a, Num (a -> b -> c)) =>
Maybe b -> Maybe c
I didn't know how to put multiple type constraints so i tried like this:
f (Just [3]) (Just [4]) (++) -- (knowing (++) can be applied to any type - being a monoid).
In this case i get the following exception:
* Couldn't match expected type `Maybe b0'
with actual type `[a1] -> [a1] -> [a1]'
* Probable cause: `(++)' is applied to too few arguments
In the third argument of `f', namely `(++)'
In the expression: f (Just [3]) (Left [3]) (++)
In an equation for `it': it = f (Just [3]) (Left [3]) (++)
f requires a monad-wrapped function as the first argument. In your first try, you didn't pass the function at all; in the second, you pass (++) as the last argument.
The following works fine:
> f (Just (++)) (Just [3]) (Just [4])
Just [3,4]
liftM2 (and more generally liftA2) already does something very similar to what you want.
> import Control.Monad (liftM2)
> liftM2 (++) (Just [3]) (Just [4])
Just [3,4]
> import Control.Applicative (liftA2)
> liftA2 (++) (Just [3]) (Just [4])
Just [3,4]

Haskell: List Comprehensions and higher-order functions

I've tried to transform the following list comprehension:
f xs = [ x+8 | (x,_) <- xs ]
using higher-order functions.
My first solution was:
f' xs = map (\(x,_) -> x+8) xs
After I tried various other approaches, I found out that the following also works:
f' xs = map((+8).fst) xs
Both versions of f' give the same (correct) output, but I don't understand why (+8).fst is equal to \(x,_) -> x+8 when using map on a list of tuples.
The definition of fst is
fst :: (a, b) -> a
fst (a, _) = a
and the definition of (.) is
(.) :: (b -> c) -> (a -> b) -> a -> c
(f . g) = \x -> f (g x)
If we use these definitions to expand your function, we get
f' xs = map ((+8) . fst) xs
f' xs = map (\x -> (+8) (fst x)) xs -- definition of (.)
f' xs = map (\x -> (+8) ((\(a, _) -> a) x)) -- definition of fst
f' xs = map (\(a, _) -> (+8) a) -- we can move the pattern matching
f' xs = map (\(a, _) -> a + 8) -- expand section
Both versions of f' give the same (correct) output, but I don't understand why (+8).fst is equal to (x,_) -> x+8 when using map on a list of tuples.
The type of fst is:
fst :: (a, b) -> a
and what it does is it takes the first element of a pair (a tuple of two elements).
The type of (+8) is:
(+8) :: Num a => a -> a
and what it does is it takes as input a Num, applies + 8 to it and returns the result.
Now, the type of (+8) . fst is:
((+8).fst) :: Num c => (c, b) -> c
which is the composition of fst and (+8). Specifically it's the function that takes as input a pair, extracts the first element and adds 8 to it.
This can be easily seen by seen an example:
((+8).fst) (3, 'a')
-- 11
The same thing happens with \ (x, _) -> x + 8. You take a pair as input (in the lambda), pattern match the first argument to x, increment it by 8 and return it:
(\ (x, _) -> x + 8) (3, 'a')
-- 11

Haskell component-by-component addition

I am trying do to the component-by-component addition of a list of tuples with the use of higher functions. The result should be the (sum of the first component, sum on the second component).
sumPointwise :: Num a => [(a,a)] -> (a,a)
sumPointwise tl = (sumPw1, sumPw2) -- 42:1
where sumPw1 = foldr (\ x y -> (fst x) + (fst y)) 0 tl
sumPw2 = foldr (\ x y -> (snd x) + (snd y)) 0 tl
But I'm getting the following error:
Couldn't match type `a' with `(a, b0)'
`a' is a rigid type variable bound by
the type signature for sumPointwise :: Num a => [(a, a)] -> (a, a)
at .hs:42:1
In the first argument of `fst', namely `y'
In the second argument of `(+)', namely `(fst y)'
In the expression: (fst x) + (fst y)
It seems like the lambda function is wrong. But I don't get it.
Thanks for your help!
The second argument of foldr is aggregate value: foldr :: (a -> b -> b) -> b -> [a] -> b. So, your expressions should look like
sumPw1 = foldr (\ x s -> (fst x) + s) 0 tl
More succinct way of solving your task is
sumPointwise tl = let (xs, ys) = unzip tl in (sum xs, sum ys)

Haskell Precedence: Lambda and operator

I found precedence and associativity is a big obstacle for me to understand what the grammar is trying to express at first glance to haskell code.
For example,
blockyPlain :: Monad m => m t -> m t1 -> m (t, t1)
blockyPlain xs ys = xs >>= \x -> ys >>= \y -> return (x, y)
By experiment, I finally got it means,
blockyPlain xs ys = xs >>= (\x -> (ys >>= (\y -> return (x, y))))
instead of
blockyPlain xs ys = xs >>= (\x -> ys) >>= (\y -> return (x, y))
Which works as:
*Main> blockyPlain [1,2,3] [4,5,6]
[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6),(3,4),(3,5),(3,6)]
I can get info from ghci for (>>=) as an operator, (infixl 1 >>=).
But there's no information for -> since it's not an operator.
Could someone of you guys give some reference to make this grammar thing easier to grasp?
The rule for lambdas is pretty simple: the body of the lambda extends as far to the right as possible without hitting an unbalanced parenthesis.
f (\x -> foo (bar baz) *** quux >>= quuxbar)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
body
A good rule of thumb seems to be that you can never make a custom operator that has precedence over built in syntactic constructs. For instance consider this example:
if b then f *** x else f *** y
Regardless of the associativity of ***, no one would expect it to binds as:
(if b then f *** x else f) *** y
There aren't a lot of syntactic constructs in Haskell (do and case are a little special because of layout syntax) but let can be used as another example:
(let x = y in y *** x) /= ((let x = y in y) *** x)

Could not deduce (Eq a) from the context (...)

I'm new to Haskell. I wrote this code:
deleteDuplicates :: [a] -> [a]
deleteDuplicates [] = []
deleteDuplicates (x:xs)
| x == (head xs) = x : (deleteDuplicates (tail xs))
| otherwise = x : (head xs) : (deleteDuplicates (tail xs))
What does this error mean and why did it occur? Am I accidentally comparing two different types somehow?
set2.hs:10:3:
Could not deduce (Eq a) from the context ()
arising from a use of `==' at set2.hs:10:3-16
Possible fix:
add (Eq a) to the context of
the type signature for `deleteDuplicates'
In the expression: x == (head xs)
In a stmt of a pattern guard for
the definition of `deleteDuplicates':
x == (head xs)
In the definition of `deleteDuplicates':
deleteDuplicates (x : xs)
| x == (head xs) = x : (deleteDuplicates (tail xs))
| otherwise = x : (head xs) : (deleteDuplicates (tail xs))
Your type signature is wrong:
deleteDuplicates :: [a] -> [a]
That says your function can work on lists of any type, a, but that isn't true! You later call:
x == (head xs)
So you must be able to compare your type for equality. Meaning the signature must be:
deleteDuplicates :: Eq a => [a] -> [a]
At times like this it's good to remove your explicit type signature, load the function in GHCi and discover what type the interpreter thinks it should have (via :t deleteDuplicates).
More Bugs
Additionally, your use of head there is a bad idea. head is a partial function and will fail when xs == []. I suggest you expand the pattern match:
deleteDuplicates (x1:x2:xs)
| x1 == x2 = ...
| otherwise = x1 : deleteDuplicates (x2:xs)
Also notice the fix to the otherwise case. You were skipping over x2, but what if x2 matched the next element in the list? Something like [1,2,2,3] would have discovered 1 /= 2 and then the recursion would have gotten the list [2,3] - oops!
The compiler is telling you that from the type signature alone it can't work out if a is an instanceof Eq.
deleteDuplicates :: Eq a => [a] -> [a]
You need to tell the compiler that a is an instance of the Eq type class by mentioning it in the signature.
The expression
x == (head xs)
requires == to be defined on the members of xs, which means a must be an instance of the typeclass Eq. Change your function's type signature to
deleteDuplicates :: Eq a => [a] -> [a]

Resources