Send Beginners mailing list submissions to beginners@haskell.org To subscribe or unsubscribe via the World Wide Web, visit http://www.haskell.org/mailman/listinfo/beginners or, via email, send a message with subject or body 'help' to beginners-requ...@haskell.org
You can reach the person managing the list at beginners-ow...@haskell.org When replying, please edit your Subject line so it is more specific than "Re: Contents of Beginners digest..." Today's Topics: 1. Re: (Implicit) equality testing using multiple function definitions (Tom Murphy) 2. Re: (Implicit) equality testing using multiple function definitions (Brandon Allbery) 3. Re: (Implicit) equality testing using multiple function definitions (Brent Yorgey) 4. Typeclasses vs. Data (Thomas) 5. Re: Typeclasses vs. Data (David Place) 6. Re: Typeclasses vs. Data (David Place) 7. Re: Typeclasses vs. Data (Thomas) 8. Re: Typeclasses vs. Data (David Place) ---------------------------------------------------------------------- Message: 1 Date: Wed, 20 Jul 2011 14:38:39 -0400 From: Tom Murphy <amin...@gmail.com> Subject: Re: [Haskell-beginners] (Implicit) equality testing using multiple function definitions To: Brandon Allbery <allber...@gmail.com> Cc: beginners <beginners@haskell.org> Message-ID: <CAO9Q0tV90qUJM1uAKazByh8jRuTTum3=kx8p+dyzku40sm2...@mail.gmail.com> Content-Type: text/plain; charset=ISO-8859-1 On 7/18/11, Brandon Allbery <allber...@gmail.com> wrote: [...] > > "Circumvents"? You make it sound like the point of typeclasses is to > restrict things. In fact, the point is to *undo* the restrictions > necessarily introduced by polymorphism: if you don't know the type of > something, you don't know what you can do with it. Typeclasses let us say > "this can be any type, but we need to be able to do <x> with it". They > don't circumvent; they *add*. > I wish I could think of a good example. Since I can't, I'll just try and make my point: In a way, the point of typeclasses _is_ to restrict things: one of the things that typeclasses enables is a compile-time error if I, say, try and add Bools: by not giving Bool a Num instance, we're expressing that something can't be expressed. There has to be a reason why we've all typed "deriving (Eq)" again and again: because sometimes we don't want, for some OurType, to be able to express: (a :: OurType) == (b :: OurType). This is the source of my confusion. Thanks for your time, Tom ------------------------------ Message: 2 Date: Wed, 20 Jul 2011 15:05:07 -0400 From: Brandon Allbery <allber...@gmail.com> Subject: Re: [Haskell-beginners] (Implicit) equality testing using multiple function definitions To: Tom Murphy <amin...@gmail.com> Cc: beginners <beginners@haskell.org> Message-ID: <cakfcl4v4o5pornjwrem97i0cmy+qk6x989s0_sro7w47sop...@mail.gmail.com> Content-Type: text/plain; charset="utf-8" On Wed, Jul 20, 2011 at 14:38, Tom Murphy <amin...@gmail.com> wrote: > There has to be a reason why we've all typed "deriving (Eq)" > again and again: because sometimes we don't want, for some OurType, to > be able to express: > (a :: OurType) == (b :: OurType). > There is a good reason, but that's not it. You're still thinking in terms of objects that carry method dictionaries around; Haskell *is not object oriented*, values are just values. Operations are defined by types, not by values. You can't ask a value how it should be compared. Typeclasses, which superficially look like objects/classes but aren't, are a way around this. A typeclass actually defines a dictionary mapping types to functions; but because values are not objects, some way needs to be provided to pass these dictionaries where they are needed. This is the function of contexts: they're actually function arguments. > f :: Eq a => a -> a -> a is a function that takes three arguments: a map of implementations, and two values of some type. Whenever this function is invoked, the compiler passes it the Eq dictionary entry for the appropriate type a. If there were multiple typeclass contexts, the map would combine all of them. It's not about hiding anything. The only reason you think there is something to hide is because an object would carry around that information and something would therefore have to hide it for it to not be available; but there are no objects here, so something has to be added to carry it around. -- brandon s allbery allber...@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://www.haskell.org/pipermail/beginners/attachments/20110720/4538663d/attachment-0001.htm> ------------------------------ Message: 3 Date: Wed, 20 Jul 2011 17:04:22 -0400 From: Brent Yorgey <byor...@seas.upenn.edu> Subject: Re: [Haskell-beginners] (Implicit) equality testing using multiple function definitions To: beginners@haskell.org Message-ID: <20110720210422.ga5...@seas.upenn.edu> Content-Type: text/plain; charset=us-ascii On Wed, Jul 20, 2011 at 02:38:39PM -0400, Tom Murphy wrote: > On 7/18/11, Brandon Allbery <allber...@gmail.com> wrote: > [...] > > > > "Circumvents"? You make it sound like the point of typeclasses is to > > restrict things. In fact, the point is to *undo* the restrictions > > necessarily introduced by polymorphism: if you don't know the type of > > something, you don't know what you can do with it. Typeclasses let us say > > "this can be any type, but we need to be able to do <x> with it". They > > don't circumvent; they *add*. > > > > I wish I could think of a good example. Since I can't, I'll just > try and make my point: In a way, the point of typeclasses _is_ to > restrict things: one of the things that typeclasses enables is a > compile-time error if I, say, try and add Bools: by not giving Bool a > Num instance, we're expressing that something can't be expressed. I think you are both right. There's a duality here, depending on your point of view. Consider a function type blah :: Foo a => ... a ... >From the point of view of someone *calling* this function, the Foo constraint *adds* some restriction: you may only pass things whose type is an instance of Foo. If you try to pass anything else you will get an error. >From the point of view of someone *implementing* this function, the Foo constraint *removes* some restriction: if there was no Foo constraint you would not be able to do anything with any arguments of type 'a'; given the Foo constraint you can do anything you could have done without it, *plus* you can use any Foo methods. -Brent ------------------------------ Message: 4 Date: Wed, 20 Jul 2011 23:58:16 +0200 From: Thomas <hask...@phirho.com> Subject: [Haskell-beginners] Typeclasses vs. Data To: beginners@haskell.org Message-ID: <4e274f78.4020...@phirho.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Hello! Trying to rewrite a program I ran into a type problem with typeclasses. It's a mini-interpreter, the essential (extremely reduced) part is: eval e k = case (car e) of (Id "begin") -> eval_begin (cdr e) k eval_begin e k = eval (car e) (if isNull (cdr e) then k else (BeginCont k (cdr e))) Using "data" to define my data all is well: data Continuation = BeginCont Continuation Expression resume k e = case k of BeginCont k' es -> eval_begin es k' Unfortunately when trying to extend the program by other types of "Continuation" I must add to the data definition and add a matching clause to "resume". That is I must modify the core module. So I tried to decouple this using a typeclass like so: class Continuation a where resume :: a -> Expression -> Expression data BeginCont a = BeginCont a Expression deriving (Show) instance (Continuation a) => Continuation (BeginCont a) where resume (BeginCont k es) v = eval_begin es k This, however, results in an "infinite type" error. Is there a way to make the typeclass version typecheck? If not: How can one decouple this code in Haskell? What also puzzles me are the differences in "infinite" types. The above data declaration for "Continuation" is essentially infinite, too. But it works. And I thought I had understood this part... Any hints greatly appreciated! Thanks in advance, Thomas PS: The minimal "program" to get it type check is: data Expression = Null | Num Int | Id String | List [Expression] deriving (Eq, Show) cdr :: Expression -> Expression cdr (List []) = error "cdr Null !" cdr (List (_:[])) = Null cdr (List (l:ls)) = List ls car :: Expression -> Expression car (List l) = head l isNull Null = True isNull _ = False eval e k = case (car e) of (Id "begin") -> eval_begin (cdr e) k eval_begin e k = eval (car e) (if isNull (cdr e) then k else (BeginCont k (cdr e))) -- replace the following 5 lines... data Continuation = BeginCont Continuation Expression resume k e = case k of BeginCont k' es -> eval_begin es k' {- ... with these to see the error class Continuation a where resume :: a -> Expression -> Expression data BeginCont a = BeginCont a Expression deriving (Show) instance (Continuation a) => Continuation (BeginCont a) where resume (BeginCont k es) v = eval_begin es k -] ------------------------------ Message: 5 Date: Wed, 20 Jul 2011 18:18:42 -0400 From: David Place <d...@vidplace.com> Subject: Re: [Haskell-beginners] Typeclasses vs. Data To: Thomas <hask...@phirho.com> Cc: beginners@haskell.org Message-ID: <79c7919a-4b97-4219-a2a4-09428a5d8...@vidplace.com> Content-Type: text/plain; charset=us-ascii On Jul 20, 2011, at 5:58 PM, Thomas wrote: > class Continuation a where > resume :: a -> Expression -> Expression > > data BeginCont a = BeginCont a Expression deriving (Show) > instance (Continuation a) => Continuation (BeginCont a) where > resume (BeginCont k es) v = eval_begin es k I think we need to know the definition of Expression. if define it with a dummy type eval_begin a b = a type Expression = Int this code fragment compiles. Would you send a code fragment that will yield the error? ____________________ David Place Owner, Panpipes Ho! LLC http://panpipesho.com d...@vidplace.com ------------------------------ Message: 6 Date: Wed, 20 Jul 2011 18:23:49 -0400 From: David Place <d...@vidplace.com> Subject: Re: [Haskell-beginners] Typeclasses vs. Data To: Thomas <hask...@phirho.com> Cc: beginners@haskell.org Message-ID: <c55f6599-3b71-424f-b294-789f97cee...@vidplace.com> Content-Type: text/plain; charset=us-ascii Please disregard my previous message. I didn't read your message carefully enough. ____________________ David Place Owner, Panpipes Ho! LLC http://panpipesho.com d...@vidplace.com On Jul 20, 2011, at 5:58 PM, Thomas wrote: > Hello! > > Trying to rewrite a program I ran into a type problem with typeclasses. > > It's a mini-interpreter, the essential (extremely reduced) part is: > > eval e k = case (car e) of > (Id "begin") -> eval_begin (cdr e) k > eval_begin e k = eval (car e) (if isNull (cdr e) then k else (BeginCont k > (cdr e))) > > Using "data" to define my data all is well: > > data Continuation = > BeginCont Continuation Expression > resume k e = case k of > BeginCont k' es -> eval_begin es k' > > Unfortunately when trying to extend the program by other types of > "Continuation" I must add to the data definition and add a matching clause to > "resume". That is I must modify the core module. > So I tried to decouple this using a typeclass like so: > > class Continuation a where > resume :: a -> Expression -> Expression > > data BeginCont a = BeginCont a Expression deriving (Show) > instance (Continuation a) => Continuation (BeginCont a) where > resume (BeginCont k es) v = eval_begin es k > > This, however, results in an "infinite type" error. > > Is there a way to make the typeclass version typecheck? > If not: How can one decouple this code in Haskell? > > What also puzzles me are the differences in "infinite" types. > The above data declaration for "Continuation" is essentially infinite, too. > But it works. And I thought I had understood this part... > > Any hints greatly appreciated! > Thanks in advance, > Thomas > > > PS: > The minimal "program" to get it type check is: > > data Expression = Null | Num Int | Id String | List [Expression] > deriving (Eq, Show) > > cdr :: Expression -> Expression > cdr (List []) = error "cdr Null !" > cdr (List (_:[])) = Null > cdr (List (l:ls)) = List ls > > car :: Expression -> Expression > car (List l) = head l > > isNull Null = True > isNull _ = False > > eval e k = case (car e) of > (Id "begin") -> eval_begin (cdr e) k > > eval_begin e k = eval (car e) (if isNull (cdr e) then k else (BeginCont k > (cdr e))) > > -- replace the following 5 lines... > data Continuation = > BeginCont Continuation Expression > > resume k e = case k of > BeginCont k' es -> eval_begin es k' > > {- ... with these to see the error > class Continuation a where > resume :: a -> Expression -> Expression > > data BeginCont a = BeginCont a Expression deriving (Show) > instance (Continuation a) => Continuation (BeginCont a) where > resume (BeginCont k es) v = eval_begin es k > -] > > _______________________________________________ > Beginners mailing list > Beginners@haskell.org > http://www.haskell.org/mailman/listinfo/beginners ------------------------------ Message: 7 Date: Thu, 21 Jul 2011 00:26:19 +0200 From: Thomas <hask...@phirho.com> Subject: Re: [Haskell-beginners] Typeclasses vs. Data To: David Place <d...@vidplace.com> Cc: beginners@haskell.org Message-ID: <4e27560b.1060...@phirho.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Hello David! Thank you for taking the time. Here is a complete fragment that shows the error: data Expression = Null | Num Int | Id String | List [Expression] deriving (Eq, Show) cdr :: Expression -> Expression cdr (List []) = error "cdr Null !" cdr (List (_:[])) = Null cdr (List (l:ls)) = List ls car :: Expression -> Expression car (List l) = head l car n = error (show n) isNull Null = True isNull _ = False eval e k = case (car e) of (Id "begin") -> eval_begin (cdr e) k eval_begin e k = eval (car e) (if isNull (cdr e) then k else (BeginCont k (cdr e))) class Continuation a where resume :: a -> Expression -> Expression data BeginCont a = BeginCont a Expression deriving (Show) instance (Continuation a) => Continuation (BeginCont a) where resume (BeginCont k es) v = eval_begin es k Regards, Thomas On 21.07.2011 00:18, David Place wrote: > On Jul 20, 2011, at 5:58 PM, Thomas wrote: > >> class Continuation a where >> resume :: a -> Expression -> Expression >> >> data BeginCont a = BeginCont a Expression deriving (Show) >> instance (Continuation a) => Continuation (BeginCont a) where >> resume (BeginCont k es) v = eval_begin es k > > I think we need to know the definition of Expression. if define it with a > dummy type > > eval_begin a b = a > type Expression = Int > > this code fragment compiles. Would you send a code fragment that will yield > the error? > ____________________ > David Place > Owner, Panpipes Ho! LLC > http://panpipesho.com > d...@vidplace.com > > ------------------------------ Message: 8 Date: Wed, 20 Jul 2011 18:40:45 -0400 From: David Place <d...@vidplace.com> Subject: Re: [Haskell-beginners] Typeclasses vs. Data To: Thomas <hask...@phirho.com> Cc: beginners@haskell.org Message-ID: <1cda3bbb-7172-4a15-9b64-daf7a1273...@vidplace.com> Content-Type: text/plain; charset=iso-8859-1 On Jul 20, 2011, at 6:26 PM, Thomas wrote: > Thank you for taking the time. > Here is a complete fragment that shows the error: Hi, Thomas. I'm very sympathetic. I hate it when I get an error like this. I looked at your code and the solution didn't jump off the page, maybe it will for someone else. In the meantime, I suggest this strategy. Carefully give type signatures to all of your functions. This way you can help the type checker give better error messages. The type inference algorithm can go away into crazy land if you give it a nonsense definition. ___________________ David Place Owner, Panpipes Ho! LLC http://panpipesho.com d...@vidplace.com ------------------------------ _______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners End of Beginners Digest, Vol 37, Issue 40 *****************************************