On 22 Apr 2008, at 8:03 PM, Derek Elkins wrote:
> On Mon, 2008-04-21 at 22:58 -0700, Jonathan Cast wrote:
>>> class Forceable alpha where
>> seq :: alpha -> beta -> beta
>>>> Instances derived automatically by the compiler, when possible, for
>> every type (like Typeable should be). We can omit functions if
>> desired (I don't remember why I thought this was a good idea). When
>> you say
>>>> f :: alpha -> beta
>>>> or
>>>> f :: C alpha => alpha -> beta
>>>> The compiler adds implicit Forceable constraints on alpha and beta.
>> But, if you say
>>>> f :: !Forceable alpha => alpha -> beta
>>>> The compiler leaves the Forceable alpha constraint off. Then you can
>> say
>>>> build :: (forall c. !Forceable c => (a -> c -> c) -> c -> c) -> [a]
>>>> And the foldr/build law is still sound.
>> Why do you want types that lie, plus some crazy ad-hoc special case?
> Why not just let f :: a -> b mean what you write as f :: !Forceable
> a =>
> a -> b exactly as it would if seq were moved (back) into a class?
> Then
> the free theorems would hold for the types as stated.
See /Being Lazy with Class/, on why seq was made polymorphic in the
first place. I don't /want/ this design, but the most common case is
that you don't care, for a type variable alpha, whether seq can be
used on alpha or not. When you do care, the most common case is that
you want seq, and adding seq where it wasn't previously legal
requires a chain of modifications reminiscent of const poisoning.
I'm willing to consider seq :: a -> b -> b a practical necessity, and
compromise with it, as long as I can still declare properly
parametric types on command.
jcc
PS ‘Lie’ is a bit strong. A lie is a statement crafted to have a
meaning not in the belief set of the speaker. The meaning of a
Haskell type judgement is given by the language. So
square :: Num alpha => alpha -> alpha
square x = x ** 2
contains a lie. But I don't think seq :: alpha -> beta -> beta does.