Problem trying to get class Bounded to work

classic Classic list List threaded Threaded
18 messages Options
Reply | Threaded
Open this post in threaded view
|

Problem trying to get class Bounded to work

Brian Hulley
Hi -
I've got the following function which doesn't compile:

  createMonoMultiFont
      :: (MonadException m, Enum i, Bounded i)
      => [(i, Font, Colour)] -> m (MonoMultiFont i)
  createMonoMultiFont elements =
      liftIO . block $ do
           mmfRaw <- duma_MonoMultiFont_create (fromEnum (maxBound::i))
           mmfPtr <- newForeignPtr duma_MonoMultiFont_Release mmfRaw
           return $ MonoMultiFont mmfPtr

The problem is that ghc complains that there is no instance for Bounded i
even though I've written "Bounded i" in the type declaration for the
function.

I was expecting that I could use the same type variables in the function
body as in the type signature so that I could use maxBound::i to find the
max bound of whatever type is instantiated to i.

What am I doing wrong here, and is it possible to create such a  function?

Thanks, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Brian Hulley
Brian Hulley wrote:

> Hi -
> I've got the following function which doesn't compile:
>
>  createMonoMultiFont
>      :: (MonadException m, Enum i, Bounded i)
>      => [(i, Font, Colour)] -> m (MonoMultiFont i)
>  createMonoMultiFont elements =
>      liftIO . block $ do
>           mmfRaw <- duma_MonoMultiFont_create (fromEnum (maxBound::i))
>           mmfPtr <- newForeignPtr duma_MonoMultiFont_Release mmfRaw
>           return $ MonoMultiFont mmfPtr
>
> The problem is that ghc complains that there is no instance for
> Bounded i even though I've written "Bounded i" in the type
> declaration for the function.

Here is a gross hack that compiles:

createMonoMultiFont elements =
      liftIO . block $ do
          let
              (onei,_,_):_ = (undefined, undefined, undefined) : elements
              upper :: Bounded a => a -> a
              upper _ = maxBound
              last = upper onei

          mmfRaw <- duma_MonoMultiFont_create (fromEnum last)
          -- adding of elements to mmfRaw ommitted for clarity
          mmfPtr <- newForeignPtr duma_MonoMultiFont_Release mmfRaw
          return $ MonoMultiFont mmfPtr

Still, it would be nice to be able to just write (maxBound::i) since the
dictionary for i is present in the result.

Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

haskell-2
In reply to this post by Brian Hulley
See "7.4.10.3 Declaration type signatures" in the manual:
http://haskell.org/ghc/docs/6.4.2/html/users_guide/type-extensions.html#decl-type-sigs

At the moment, the "i" in the type declaration and in the body are not the same "i".

To get the "i" from the type declaration for createMonoMultiFont into the scope
of the definition, the trick is to add the otherwise useless/forbidden "forall i
m." to the type declaration:

createMonoMultiFont
     :: forall i m.(MonadException m, Enum i, Bounded i)
     => [(i, Font, Colour)] -> m (MonoMultiFont i)
createMonoMultiFont elements =
     liftIO . block $ do
          mmfRaw <- duma_MonoMultiFont_create (fromEnum (maxBound::i))
          mmfPtr <- newForeignPtr duma_MonoMultiFont_Release mmfRaw
          return $ MonoMultiFont mmfPtr

The above is now accepted by ghci on my GHC 6.4.1 installation on OS X.

--
Chris


Brian Hulley wrote:

> Hi -
> I've got the following function which doesn't compile:
>
>  createMonoMultiFont
>      :: (MonadException m, Enum i, Bounded i)
>      => [(i, Font, Colour)] -> m (MonoMultiFont i)
>  createMonoMultiFont elements =
>      liftIO . block $ do
>           mmfRaw <- duma_MonoMultiFont_create (fromEnum (maxBound::i))
>           mmfPtr <- newForeignPtr duma_MonoMultiFont_Release mmfRaw
>           return $ MonoMultiFont mmfPtr
>
> The problem is that ghc complains that there is no instance for Bounded
> i even though I've written "Bounded i" in the type declaration for the
> function.
>
> I was expecting that I could use the same type variables in the function
> body as in the type signature so that I could use maxBound::i to find
> the max bound of whatever type is instantiated to i.
>
> What am I doing wrong here, and is it possible to create such a  function?
>
> Thanks, Brian.
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Cale Gibbard
In reply to this post by Brian Hulley
Hello,

There's a prelude function called asTypeOf which might help here:
asTypeOf :: a -> a -> a
asTypeOf = const

You can use maxBound `asTypeOf` (fst3 . head $ elements)

Another option is GHC's scoped type variables, which you use by adding
a type signature to your pattern. See:
http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#scoped-type-variables

 - Cale

On 22/05/06, Brian Hulley <[hidden email]> wrote:

> Brian Hulley wrote:
> > Hi -
> > I've got the following function which doesn't compile:
> >
> >  createMonoMultiFont
> >      :: (MonadException m, Enum i, Bounded i)
> >      => [(i, Font, Colour)] -> m (MonoMultiFont i)
> >  createMonoMultiFont elements =
> >      liftIO . block $ do
> >           mmfRaw <- duma_MonoMultiFont_create (fromEnum (maxBound::i))
> >           mmfPtr <- newForeignPtr duma_MonoMultiFont_Release mmfRaw
> >           return $ MonoMultiFont mmfPtr
> >
> > The problem is that ghc complains that there is no instance for
> > Bounded i even though I've written "Bounded i" in the type
> > declaration for the function.
>
> Here is a gross hack that compiles:
>
> createMonoMultiFont elements =
>       liftIO . block $ do
>           let
>               (onei,_,_):_ = (undefined, undefined, undefined) : elements
>               upper :: Bounded a => a -> a
>               upper _ = maxBound
>               last = upper onei
>
>           mmfRaw <- duma_MonoMultiFont_create (fromEnum last)
>           -- adding of elements to mmfRaw ommitted for clarity
>           mmfPtr <- newForeignPtr duma_MonoMultiFont_Release mmfRaw
>           return $ MonoMultiFont mmfPtr
>
> Still, it would be nice to be able to just write (maxBound::i) since the
> dictionary for i is present in the result.
>
> Brian.
>
> _______________________________________________
> Haskell-Cafe mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/haskell-cafe
>
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Brian Hulley
In reply to this post by haskell-2
Chris Kuklewicz wrote:

> See "7.4.10.3 Declaration type signatures" in the manual:
> http://haskell.org/ghc/docs/6.4.2/html/users_guide/type-extensions.html#decl-type-sigs
>
> At the moment, the "i" in the type declaration and in the body are
> not the same "i".
>
> To get the "i" from the type declaration for createMonoMultiFont into
> the scope
> of the definition, the trick is to add the otherwise
> useless/forbidden "forall i m." to the type declaration:
>
> createMonoMultiFont
>     :: forall i m.(MonadException m, Enum i, Bounded i)
>     => [(i, Font, Colour)] -> m (MonoMultiFont i)
> createMonoMultiFont elements =
>     liftIO . block $ do
>          mmfRaw <- duma_MonoMultiFont_create (fromEnum (maxBound::i))
>          mmfPtr <- newForeignPtr duma_MonoMultiFont_Release mmfRaw
>          return $ MonoMultiFont mmfPtr
>
> The above is now accepted by ghci on my GHC 6.4.1 installation on OS
> X.

Thanks - I'd completely forgotten about the need to add an explicit forall,
because although I read the section a while ago, the need for the forall got
clouded over in my mind by the fact that the forall is unnecessary for the
type signature itself, so the need for the forall seems to be just a good
way to slot this extra functionality into the language while remaining
backwards compatible with H98.

I wonder if Haskell' will automatically make type variables scope over the
function body (without an explicit forall)? Is there any reason why they
shouldn't always do so?

Thanks again,
Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Brian Hulley
In reply to this post by Cale Gibbard
Cale Gibbard wrote:

> Hello,
>
> There's a prelude function called asTypeOf which might help here:
> asTypeOf :: a -> a -> a
> asTypeOf = const
>
> You can use maxBound `asTypeOf` (fst3 . head $ elements)
>
> Another option is GHC's scoped type variables, which you use by adding
> a type signature to your pattern. See:
> http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#scoped-type-variables

Hi Cale -
Thanks for the solutions. The GHC scoped typed variables seem to be the best
solution since they would seem to be the only way to implement something
where the type only occurs in the result eg (if the actual fonts were to be
added later):

   createMonoMultiFont
       :: forall i m . (MonadException m, Enum i, Bounded i)
       => m (MonoMultiFont i)

Thanks,
Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re[2]: Problem trying to get class Bounded to work

Bulat Ziganshin-2
Hello Brian,

Tuesday, May 23, 2006, 4:05:45 AM, you wrote:

> Thanks for the solutions. The GHC scoped typed variables seem to be the best
> solution since they would seem to be the only way to implement something
> where the type only occurs in the result eg (if the actual fonts were to be
> added later):

>    createMonoMultiFont
>        :: forall i m . (MonadException m, Enum i, Bounded i)
>        => m (MonoMultiFont i)

malloc :: Storable a => IO (Ptr a)
malloc  = doMalloc undefined
  where
    doMalloc       :: Storable b => b -> IO (Ptr b)
    doMalloc dummy  = mallocBytes (sizeOf dummy)


these tricks are better if you need to write code that will be
compiled not only by GHC. and i also hope that Haskell' will support
scoping of type variables over the function body

--
Best regards,
 Bulat                            mailto:[hidden email]

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Ben Franksen-2
In reply to this post by Brian Hulley
On Tuesday 23 May 2006 02:00, Brian Hulley wrote:
> I wonder if Haskell' will automatically make type variables scope
> over the function body (without an explicit forall)? Is there any
> reason why they shouldn't always do so?

One I can think of is that the type signature for a function may be at
the other end of the file. Some discussion about the pros and cons can
be found here

http://www.mail-archive.com/haskell%40haskell.org/msg15738.html

and here

http://article.gmane.org/gmane.comp.lang.haskell.glasgow.user/9219

Ben
--
You've never looked into my eyes but don't you want to know
What the dark and the wild and the different know -- Melissa Etheridge
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Jacques Carette
In reply to this post by Bulat Ziganshin-2
Bulat Ziganshin wrote:

>malloc :: Storable a => IO (Ptr a)
>malloc  = doMalloc undefined
>  where
>    doMalloc       :: Storable b => b -> IO (Ptr b)
>    doMalloc dummy  = mallocBytes (sizeOf dummy)
>  
>
Is there any reason to not code this as

malloc :: Storable a => IO (Ptr a)
malloc  = mallocBytes $ sizeof undefined
?

Jacques


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Bertram Felgenhauer-2
Jacques Carette wrote:

> Bulat Ziganshin wrote:
>
> >malloc :: Storable a => IO (Ptr a)
> >malloc  = doMalloc undefined
> > where
> >   doMalloc       :: Storable b => b -> IO (Ptr b)
> >   doMalloc dummy  = mallocBytes (sizeOf dummy)
> >
> >
> Is there any reason to not code this as
>
> malloc :: Storable a => IO (Ptr a)
> malloc  = mallocBytes $ sizeof undefined

What type would the 'undefined' have in this context?

sizeOf has type Storable a => a -> Int -- that doesn't help.

The purpose of doMalloc is to force the type checker to choose
the right type for that 'undefined'.

regards,

Bertram
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Brian Hulley
In reply to this post by Jacques Carette
Jacques Carette wrote:

> Bulat Ziganshin wrote:
>
>> malloc :: Storable a => IO (Ptr a)
>> malloc  = doMalloc undefined
>>  where
>>    doMalloc       :: Storable b => b -> IO (Ptr b)
>>    doMalloc dummy  = mallocBytes (sizeOf dummy)
>>
>>
> Is there any reason to not code this as
>
> malloc :: Storable a => IO (Ptr a)
> malloc  = mallocBytes $ sizeof undefined
> ?

Yes. The supreme clevernesss of Bulat's trick is that doMalloc unifies the
type variable 'a' with the type of the argument to sizeOf, whereas "sizeOf
undefined" would be ambiguous because the type of "undefined" is not
constrained there ie:

  malloc :: Storable a => IO (Ptr a)
  malloc  = doMalloc undefined
    where
      doMalloc       :: Storable b => b -> IO (Ptr b)
      doMalloc dummy  = mallocBytes (sizeOf dummy)

  (doMalloc undefined) :: IO (Ptr a)

==>

  (doMalloc dummy) :: IO (Ptr a)

==>  -- doMalloc :: Storable b => b -> IO (Ptr b)

  dummy :: a

whereas:

  malloc  = mallocBytes $ sizeOf undefined

  malloc :: IO (Ptr a)

==>

  (mallocBytes (sizeOf undefined)) :: IO (Ptr a)

==>

  (sizeOf undefined) :: Int

==>

  undefined :: unconstrained

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Jacques Carette
In reply to this post by Bertram Felgenhauer-2
Bertram Felgenhauer wrote:

>Jacques Carette wrote:
>  
>
>>Bulat Ziganshin wrote:
>>
>>    
>>
>>>malloc :: Storable a => IO (Ptr a)
>>>malloc  = doMalloc undefined
>>>where
>>>  doMalloc       :: Storable b => b -> IO (Ptr b)
>>>  doMalloc dummy  = mallocBytes (sizeOf dummy)
>>>
>>>
>>>      
>>>
>>Is there any reason to not code this as
>>
>>malloc :: Storable a => IO (Ptr a)
>>malloc  = mallocBytes $ sizeof undefined
>>    
>>
>
>What type would the 'undefined' have in this context?
>
>sizeOf has type Storable a => a -> Int -- that doesn't help.
>
>The purpose of doMalloc is to force the type checker to choose
>the right type for that 'undefined'.
>  
>
I still don't quite see it!  To my eyes, the type of doMalloc and the
type of malloc look exactly "the same", with neither providing more
specificity than the other.  Also, the 'undefined' can be of any type,
as long as it is from class Storable.  So it is a placeholder for a
dictionary - what else does it need?  [Constraint-typing-wise, it
doesn't need anything else, but perhaps the issue is that I don't
understand Haskell's type system quite well enough].

I guess I am also asking "Is there a GOOD reason why the simpler code
can't be used?".  Or maybe what I really need is

malloc :: Storable a => IO (Ptr a)
malloc  = mallocBytes $ sizeof undefined::a

?  That would make sense to me, since in a more general function I might have 2 instances (Storable a, Storable b) available, and 2 undefineds, and I could not know how to match them up deterministically in all cases.

I guess I prefer a type annotation over a dummy function that is there just to force the type checker to believe me.  If one has to force the type checker, may as well do it with a type, not code!

Jacques
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re[2]: Problem trying to get class Bounded to work

Bulat Ziganshin-2
In reply to this post by Brian Hulley
Hello Brian,

Tuesday, May 23, 2006, 7:10:23 PM, you wrote:

> Yes. The supreme clevernesss of Bulat's trick is that doMalloc unifies the

my main trick is that i read sources of std libs :)


--
Best regards,
 Bulat                            mailto:[hidden email]

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re[2]: Problem trying to get class Bounded to work

Bulat Ziganshin-2
In reply to this post by Jacques Carette
Hello Jacques,

Tuesday, May 23, 2006, 7:13:33 PM, you wrote:

>>>>malloc :: Storable a => IO (Ptr a)
>>>>malloc  = doMalloc undefined
>>>>where
>>>>  doMalloc       :: Storable b => b -> IO (Ptr b)
>>>>  doMalloc dummy  = mallocBytes (sizeOf dummy)
>>>Is there any reason to not code this as
>>>
>>>malloc :: Storable a => IO (Ptr a)
>>>malloc  = mallocBytes $ sizeof undefined

well

1) in your code type of 'undefined' is unknown. it can be any type,
while we need 'undefined' of one concrete type, which is given in
function signature. compiler will just complain that type is not fixed
here


2) what we really need is to write

malloc :: Storable a => IO (Ptr a)
malloc  = mallocBytes $ sizeof (undefined::a)

i.e. fix type of 'undefined' to 'a'. but that is impossible in
Haskell-98


3) GHC provides language extension (see above in the thread), that
allow to use 'a' in function body if function was declared using
'forall', so this works in GHC

malloc :: forall a . Storable a => IO (Ptr a)
malloc  = mallocBytes $ sizeof (undefined::a)


4) this example is borrowed from std libs, what is common for hugs,
ghc and nhc, so they can't use ghc-specific solution. instead, this
complex trick is used. it's very unobvious, but at least it works with
any H98-compatible compiler

--
Best regards,
 Bulat                            mailto:[hidden email]

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Udo Stenzel
In reply to this post by Jacques Carette
Jacques Carette wrote:

> Bulat Ziganshin wrote:
>
> >malloc :: Storable a => IO (Ptr a)
> >malloc  = doMalloc undefined
> > where
> >   doMalloc       :: Storable b => b -> IO (Ptr b)
> >   doMalloc dummy  = mallocBytes (sizeOf dummy)
> >
> >
> Is there any reason to not code this as
>
> malloc :: Storable a => IO (Ptr a)
> malloc  = mallocBytes $ sizeof undefined
> ?
There is.  Don't you think there's a reason why doMalloc above has an
explicit type signature?  What would happen if you deleted it?


Udo.
--
"You, sir, are nothing but a pathetically lame salesdroid!
I fart in your general direction!"
        -- Randseed on #Linux

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe

signature.asc (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Brian Hulley
In reply to this post by Jacques Carette
Jacques Carette wrote:
> I guess I prefer a type annotation over a dummy function that is
> there just to force the type checker to believe me.  If one has to
> force the type checker, may as well do it with a type, not code!

I agree totally.
Also, I think there is a more general issue regarding the relative
importance of type inference when programming, since it seems to me that a
lot of awkwardness is introduced into Haskell by the insistence that the
type inference algorithm should be able to infer everything by itself to
surprise the programmer with knowledge that the programmer should already
know in the first place and could quite easily have written down directly.

An example is the fact that constructors and record field names currently
have to be unique within a whole module. If instead of this, constructors
and field names were always in seperate namespaces indexed by type, instead
of them determining the type, programming would be tremendously easier
because the same names could be reused without worrying about conflicts.

eg compare

           data Either a b = Left a | Right b   -- Prelude got there first
as usual
           data Location = Location_Left | Location_Right

           foo (Location_Left, Location_Left, Location_Left) = Left 5
           foo (Location_Left, Location_Left, Location_Right) = Right
"something"
           -- 6 more wordy patterns

with

           data Either a b = Left a | Right b
           data Location = Left | Right   -- all names local to type
Location

           foo :: (Location, Location, Location) -> Either Int String
           foo (Left, Left, Left) = Left 5
           foo (Left, Left, Right) = Right "something"
           -- 6 more simple patterns

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Bugzilla from robdockins@fastmail.fm
In reply to this post by Jacques Carette

On May 23, 2006, at 11:13 AM, Jacques Carette wrote:

> Bertram Felgenhauer wrote:
>
>> Jacques Carette wrote:
>>
>>> Bulat Ziganshin wrote:
>>>
>>>
>>>> malloc :: Storable a => IO (Ptr a)
>>>> malloc  = doMalloc undefined
>>>> where
>>>>  doMalloc       :: Storable b => b -> IO (Ptr b)
>>>>  doMalloc dummy  = mallocBytes (sizeOf dummy)
>>>>
>>>>
>>>>
>>> Is there any reason to not code this as
>>>
>>> malloc :: Storable a => IO (Ptr a)
>>> malloc  = mallocBytes $ sizeof undefined
>>>
>>
>> What type would the 'undefined' have in this context?
>>
>> sizeOf has type Storable a => a -> Int -- that doesn't help.
>>
>> The purpose of doMalloc is to force the type checker to choose
>> the right type for that 'undefined'.
>>
> I still don't quite see it!  To my eyes, the type of doMalloc and  
> the type of malloc look exactly "the same", with neither providing  
> more specificity than the other.  Also, the 'undefined' can be of  
> any type, as long as it is from class Storable.  So it is a  
> placeholder for a dictionary - what else does it need?  [Constraint-
> typing-wise, it doesn't need anything else, but perhaps the issue  
> is that I don't understand Haskell's type system quite well enough].
>
> I guess I am also asking "Is there a GOOD reason why the simpler  
> code can't be used?".  Or maybe what I really need is
>
> malloc :: Storable a => IO (Ptr a)
> malloc  = mallocBytes $ sizeof undefined::a
>
> ?  That would make sense to me, since in a more general function I  
> might have 2 instances (Storable a, Storable b) available, and 2  
> undefineds, and I could not know how to match them up  
> deterministically in all cases.
>
> I guess I prefer a type annotation over a dummy function that is  
> there just to force the type checker to believe me.  If one has to  
> force the type checker, may as well do it with a type, not code!


Sure, and there's good reasons to prefer this.  It's not Haskell 98,  
however.  In Haskell 98 type variables in type signatures are not in  
scope in the body of the function.  Adding the type annotation  
(undefined::a) is the same as (undefined::forall a. a) because free  
type variables are automatically bound with universal quantifiers.  
Obviously, that isn't what you want here.  So instead one has to play  
games with the type checker to force the right things to unify.  
Another thing you'll see sometimes is lazy pattern matching and  
'asTypeOf' used to get at type variables inside data types.


GHC has an extension to allow scoped type variables and there's also  
a Haskell' ticket for it.

http://www.haskell.org/ghc/docs/latest/html/users_guide/type- 
extensions.html#scoped-type-variables
http://hackage.haskell.org/trac/haskell-prime/wiki/ScopedTypeVariables




Rob Dockins

Speak softly and drive a Sherman tank.
Laugh hard; it's a long way to the bank.
           -- TMBG



_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Problem trying to get class Bounded to work

Brian Hulley
In reply to this post by Ben Franksen-2
Benjamin Franksen wrote:

> On Tuesday 23 May 2006 02:00, Brian Hulley wrote:
>> I wonder if Haskell' will automatically make type variables scope
>> over the function body (without an explicit forall)? Is there any
>> reason why they shouldn't always do so?
>
> One I can think of is that the type signature for a function may be at
> the other end of the file. Some discussion about the pros and cons can
> be found here
>
> http://www.mail-archive.com/haskell%40haskell.org/msg15738.html
>
> and here
>
> http://article.gmane.org/gmane.comp.lang.haskell.glasgow.user/9219

Thanks for the links. I hadn't realised there were so many hard choices to
make in the design of the type system and that it is not clear that there is
a unique correct answer to the problem. I'll have to do some further reading
to find the meaning of "rigid" and "wobbly" and "non-type type variables" or
type variables which are not types... ;-)

I must admit I also don't understand why there is a difference between let
bindings and case bindings. (I know let bindings are lazy but I don't see
what difference this makes to the type system) Or is the difference just due
to the desire to still have a monomorphism restriction and/or limitations
with HM type inference? Would the difference be needed if a different type
system (eg intersection types with principal *typing* property instead of HM
types which only have a principal types property) were used?

I was very surprised at the decision to use the otherwise redundant "forall"
to make a distinction between whether or not type variables are scoped,
since a simple compiler option could have been used to turn on/off implicit
scoping instead to preserve compatibility with H98 modules.

One issue seems to be that H98 compatibility (eg implicit forall) is
fundamentally incompatible with a simple uniform approach to typing in the
presence of all the advanced type extensions that have been added since H98
was designed.

It still seems there are too many different cases. Perhaps there are
conflicting demands on the type system and the rejection of some of these
demands would lead to a simpler solution?

Robert Dockins wrote:
> GHC has an extension to allow scoped type variables and there's also
> a Haskell' ticket for it.
>
> http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#scoped-type-variables
> http://hackage.haskell.org/trac/haskell-prime/wiki/ScopedTypeVariables

Hopefully the ticket will get more detailed and concrete and
rationally-reconstructed to remove the existing quirks and "thence grow to a
point" as Shakespeare might have said, in due course.

Regards, Brian.

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe