Fwd: [Haskell-cafe] Class

Daniel Fischer daniel.is.fischer at web.de
Thu Nov 2 08:13:02 EST 2006


Am Donnerstag, 2. November 2006 10:57 schrieb Slavomir Kaslev:
> ---------- Forwarded message ----------
> From: Slavomir Kaslev <slavomir.kaslev at gmail.com>
> Date: Nov 2, 2006 10:47 AM
> Subject: Re: [Haskell-cafe] Class
> To: Daniel Fischer <daniel.is.fischer at web.de>
>
> On 11/2/06, Daniel Fischer <daniel.is.fischer at web.de> wrote:
> > Am Donnerstag, 2. November 2006 00:06 schrieb Slavomir Kaslev:
> > > Hello.
> > >
> > > I am new to Haskell and I am going through "Haskell: The craft of
> > > functional programming". I am trying to grasp haskell's classes and
> > > instances, so here is slightly modified code from the book:
> > >
> > > class Show a => Visible a where
> > >     toString :: a -> String
> > >     toString = show
> > >     size :: a -> Int
> > >     size = length . show
> > >
> > > instance Visible a => Visible [a] where
> > >     toString = concat . map toString
> > >     size = foldl (+) 0 . map size
> > >
> > > vSort :: (Visible a, Ord a) => [a] -> String
> > > vSort = toString . List.sort
> >
> >                      ^^^^^^^
> > my ghc complained that List.sort is not in scope, did you import
> > Data.List as List?
>
> Yes, I did imported Data.List. My mistake for forgetting to add it in the
> post.

That was not quite what I meant. If I import Data.List, what is in scope are
plain "sort" and qualified "Data.List.sort", not "List.sort". To have the 
latter in scope, I think you would have to 
import (qualified) Data.List as List

>
> > > s = vSort [1..3]
> > >
> > > Unfortunetly in ghc it gives the following type error:
> > >     Ambiguous type variable `a' in the constraints:
> > >       `Visible a' arising from use of `vSort' at d:/tmp.hs:83:4-8
> > >       `Enum a' arising from the arithmetic sequence `1 .. 3' at
> > > d:/tmp.hs:83:10-15
> > >       `Num a' arising from the literal `3' at d:/tmp.hs:83:14
> > >       `Ord a' arising from use of `vSort' at d:/tmp.hs:83:4-8
> > >     Probable fix: add a type signature that fixes these type
> > > variable(s) Failed, modules loaded: none.
> > >
> > > As you can see, Visible is nothing more than an adapter to the Show
> > > class. How I got thing so far, [1..3] :: (Num a, Enum a) => [a], has a
> > > Show instance so does class Num (which 'subclasses' Show). Therefore,
> > > I can't see any reason why toString function can't call show from
> > > those instances.
> >
> > First problem: class Visible has no instances yet, so even if you
> > disambiguate the type by writing e.g.
> > s = vSort [1 :: Int .. 3], you'll get an error message:
> > Visible.hs:20:4:
> >     No instance for (Visible Int)
> >       arising from use of `vSort' at Visible.hs:20:4-8
> >     Probable fix: add an instance declaration for (Visible Int)
> >     In the definition of `s': s = vSort ([1 :: Int .. 3])
>
> Visible 'subclasses' Show. Doesn't this mean that Visible should be
> defined for all types with Show instances? I don't want to write
> Visible Int, if ghc has already defined a Show Int instance.

No, quite reverse, that Visible is a subclass of Show means that all instances 
of Visible must also be instances of Show. Perhaps the notation

class Show a => Visible a where

mislead you, as it may be read that Show implies Visible, while it actually 
means that Visible _requires_ Show.
>
> > And the second problem:
> > The typechecker has no means of determining which type 1 should have.
> > By virtue of the fact that numeric literals are overloaded in Haskell, it
> > has type Num a => a. The use of enumFromTo adds the Enum a constraint and
> > vSort adds Ord and Visible, however there may be many types satisfying
> > these constraints and ghc says it's up to you to select one.
> > And even if there is only one instance of Visible declared, ghc (nor, as
> > far as I know, any other Haskell implementation) won't select that
> > because there might, somewhere in a long-forgotten directory, lie a
> > module dormant in which another instance satisfying all constraints is
> > declared.
> > To sum up: instance selection is left to the user, the compiler does only
> > type _inference_. Often that determines which instance fits, but
> > sometimes you have to give an expression type signature to tell the
> > compiler what to choose.
>
> I agree with second problem you pointed out. Thanks for mentioning it.
>
> --
> Slavomir Kaslev

No sweat,
Daniel



More information about the Haskell-Cafe mailing list