Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

HASKELL: repeated variable in pattern? (Newbie question)

411 views
Skip to first unread message

Alec

unread,
Dec 22, 2001, 2:41:41 AM12/22/01
to
Hi

The following code
------------------------------------------------------
module Remove() where

f :: a -> [a] -> [a] -- Remove an element
f x [] = []
f x (x:whatever) = whatever
f x (y:whatever) = x:whatever
------------------------------------------------------
Gives an error:

Reading file "remove.hs":
Dependency analysis
ERROR "remove.hs" (line 5): Repeated variable "x" in pattern

Why is it that a variable can't be repeated and how am I supposed to do
this (construct a generic element removal function)

Alec
P.S. On a different note, what's an arity?

Alec

unread,
Dec 22, 2001, 2:48:15 AM12/22/01
to
Alec wrote:

> Hi
>
> The following code
> ------------------------------------------------------
> module Remove() where
>
> f :: a -> [a] -> [a] -- Remove an element
> f x [] = []
> f x (x:whatever) = whatever
> f x (y:whatever) = x:whatever
> ------------------------------------------------------

I meant
f x (y:whatever) = x: f whatever
in the last line of course. (Same error)

Jón Fairbairn

unread,
Dec 22, 2001, 7:25:20 AM12/22/01
to
Alec <alecANTIS...@yahoo.com> writes:

I forget the technical reasons why this isn't allowed, but you can do
it with a guard. Where you want to write

f x x = blurp
f x y = blop
write

f x y | x == y = blurp
| otherwise = blop

> > Alec
> > P.S. On a different note, what's an arity?

the number of parameters something takes.

--
Jón Fairbairn Jon.Fa...@cl.cam.ac.uk

Peter G. Hancock

unread,
Dec 22, 2001, 8:54:00 AM12/22/01
to
>>>>> "Jón" == Jón Fairbairn <j...@cl.cam.ac.uk> writes:

Jón> I forget the technical reasons why this isn't allowed, but
Jón> you can do it with a guard. Where you want to write

Jón> f x x = blurp f x y = blop write

Jón> f x y | x == y = blurp | otherwise = blop

This has the type f :: (Eq a) -> a -> a -> something.

I think that Miranda allowed `non-linear' (repeated) parameters when
defining a function. It seems there are two choices:

1. Allow f x x = ... as sugar for f x y | x == y = ...
2. Insist on non-repetitious parameter lists, and that
equality guards are put in explicitly.

The Right Choice is 2, ISTM. It catches more mistakes.

Peter Hancock

Alec

unread,
Dec 22, 2001, 12:39:37 PM12/22/01
to
Jón Fairbairn wrote:

> Alec <alecANTIS...@yahoo.com> writes:
> Where you want to write
>
> f x x = blurp
> f x y = blop
> write
>
> f x y | x == y = blurp
> | otherwise = blop


This modified code:
------------------------------------------------------
module Remove() where

f :: a -> [a] -> [a] -- Remove an element
f x [] = []

f x (y:whatever) | x == y = f x whatever
| otherwise = y: f x whatever
------------------------------------------------------
still gives an error (but a different one):

Reading file "remove.hs":
Type checking
ERROR "remove.hs" (line 5): Cannot justify constraints in explicitly typed
binding
*** Expression : f
*** Type : a -> [a] -> [a]
*** Given context : ()
*** Constraints : Eq a


Thanks

Alec

Alec

unread,
Dec 22, 2001, 1:17:17 PM12/22/01
to
Peter G. Hancock wrote:

>>>>>> "Jón" == Jón Fairbairn <j...@cl.cam.ac.uk> writes:
>
> Jón> I forget the technical reasons why this isn't allowed, but
> Jón> you can do it with a guard. Where you want to write
>
> Jón> f x x = blurp f x y = blop write
>
> Jón> f x y | x == y = blurp | otherwise = blop
>
> This has the type f :: (Eq a) -> a -> a -> something.
>
> I think that Miranda allowed `non-linear' (repeated) parameters when
> defining a function. It seems there are two choices:
>
> 1. Allow f x x = ... as sugar for f x y | x == y = ...

Not only that, why not allow
f g(x) h(x) = ... as "sugar" for f g(x) h(y) | x == y = ...?

Alec

Jón Fairbairn

unread,
Dec 22, 2001, 3:50:40 PM12/22/01
to
Alec <alecANTIS...@yahoo.com> writes:
> This modified code:
> ------------------------------------------------------
> module Remove() where
>
> f :: a -> [a] -> [a] -- Remove an element
> f x [] = []
> f x (y:whatever) | x == y = f x whatever
> | otherwise = y: f x whatever
> ------------------------------------------------------
> still gives an error (but a different one):
>
> Reading file "remove.hs":
> Type checking
> ERROR "remove.hs" (line 5): Cannot justify constraints in explicitly typed
> binding
> *** Expression : f
> *** Type : a -> [a] -> [a]
> *** Given context : ()
> *** Constraints : Eq a

You've told it that f is a polymorphic function (working for _all_ a),
but then used equality and prevented it from working on types that
don't have equality.

Either omit the type declaration and let the compiler discover the
type, or write something more honest like:

f :: Eq a => a -> [a] -> [a]


--
Jón Fairbairn Jon.Fa...@cl.cam.ac.uk

Jón Fairbairn

unread,
Dec 22, 2001, 3:54:42 PM12/22/01
to
Alec <alecANTIS...@yahoo.com> writes:

> Not only that, why not allow
> f g(x) h(x) = ... as "sugar" for f g(x) h(y) | x == y = ...?

That syntax is no good since f g(x) h(x) = ... is syntactically
the same as f g x h x

f (g == x) (h == x) might work, but you aren't gaining much. Guards
are a more general mechanism since you can write f x y | x < y = . . .

--
Jón Fairbairn Jon.Fa...@cl.cam.ac.uk

Alec

unread,
Dec 22, 2001, 4:46:07 PM12/22/01
to
Jón Fairbairn wrote:

> Either omit the type declaration and let the compiler discover the
> type,

This finally works. Thanks!

> or write something more honest like:
>
> f :: Eq a => a -> [a] -> [a]

What does "Eq a" mean?

Alec

Peter G. Hancock

unread,
Dec 22, 2001, 8:31:07 PM12/22/01
to
>>>>> "alecANTISPAM314159" == alecANTISPAM314159 <Alec> writes:

alecANTISPAM314159> Not only that, why not allow f g(x) h(x) =
alecANTISPAM314159> ... as "sugar" for f g(x) h(y) | x == y = ...?

Do you mean allowing patterns (built out of constructors) in which the
pattern variables needn't be distinct?

On the face of it that seems a sensible idea, if you are going to allow
the variables in (uninformative) "x" patterns to be repeated, and explain
it with equality guards.

I still think it is a very sound idea that when you are defining a
function, by pattern matching or not, the parameters should be
distinct.

[If anyone is interested, this is a really interesting question for
dependent type systems: whether they admit a generic identity type, having
a definition something like

> data Id (A : Type) (a : A) (a : A) = Refl (a : A)

with repeated parameters.]
--
Peter Hancock

Gaurav Sharma

unread,
Dec 23, 2001, 12:00:13 AM12/23/01
to

"Alec" <alecANTIS...@yahoo.com> wrote in message
news:a02uv0$au6$1...@newsmaster.cc.columbia.edu...

a is part of the Eq class.

--
Gaurav Sharma


Jón Fairbairn

unread,
Dec 23, 2001, 8:26:40 AM12/23/01
to
"Gaurav Sharma" <gaurav...@ic.ac.uk> writes:

To elaborate a little further, in f :: Eq a => a -> [a] -> [a], "Eq a
=>" is a context that requires that the variable a in the rest of the
type belong to the class Eq.

The standard prelude defines Eq like this:

class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)


in other words, that context says that f will work for any type a if a
has been made an instance of Eq, which in turn means that there is an
(==) operator for a. That's what you needed, after all.


--
Jón Fairbairn Jon.Fa...@cl.cam.ac.uk

Olaf Klischat

unread,
Dec 29, 2001, 11:08:18 PM12/29/01
to
j...@cl.cam.ac.uk (Jón Fairbairn) writes:

How did the compiler in Alec's example know that "a" had to belong to
class "Eq"? I mean, any class that declares "==" would have matched,
right?

Olaf

Jón Fairbairn

unread,
Dec 30, 2001, 8:50:36 AM12/30/01
to
Olaf Klischat <klis...@cs.tu-berlin.de> writes:

> How did the compiler in Alec's example know that "a" had to belong to
> class "Eq"? I mean, any class that declares "==" would have matched,
> right?

I think you are mixing up the OO notion of class with the polymorphic
type notion of class. You aren't allowed to define type classes that
use the same function names as other type classes. So in Haskell, the
only class that has (==) is Eq.

For type classes, the names and types of the operators are what
defines them.

--
Jón Fairbairn Jon.Fa...@cl.cam.ac.uk

0 new messages