Type Constraints on Data Constructors

{- continuing discussion from beginners@ -} I have code such as class Foo f where foo :: a -> f a data Bar f a = Foo f => Bar {bar :: f a} instance Foo (Bar f) where foo a = Bar $ foo a GHC insists that I put Foo f => on the instance declaration, even though the constructor for Bar implies this. Is there any reason why GHC cannot infer this constraint from the Bar constructor? One issue raised in the beginners thread is that undefined :: Bar f a is not Foo f, but as undefined cannot be evaluated, this would not appear to be a problem.

data Bar f a = Foo f => Bar {bar :: f a}
The class context on the data constructor buys you nothing extra in terms of expressivity in the language. All it does is force you to repeat the context on every function that uses the datatype. For this reason, the language committee has decided that the feature will be removed in the next revision of Haskell. Regards, Malcolm

On Wed, Jun 8, 2011 at 3:15 PM, Malcolm Wallace
data Bar f a = Foo f => Bar {bar :: f a}
The class context on the data constructor buys you nothing extra in terms of expressivity in the language. All it does is force you to repeat the context on every function that uses the datatype. For this reason, the language committee has decided that the feature will be removed in the next revision of Haskell.
You're thinking of a context on the type constructor, i.e.,
data Foo f => Bar f a = Bar { bar :: f a }
The reason the original code does not work is that the constructor
only adds Foo f to the class context during pattern matching. So, for
example, this works:
baz :: Bar f a -> a -> f a -- n.b., no Foo context
baz (Bar _) = foo
But the code in the original post is trying to create a value of type
Bar f a, so the context is needed.
--
Dave Menendez

Malcolm Wallace
data Bar f a = Foo f => Bar {bar :: f a}
The class context on the data constructor buys you nothing extra in terms of
expressivity in the language.
All it does is force you to repeat the context on every function that uses the datatype. For this reason, the language committee has decided that the feature will be removed in the next revision of Haskell.
Regards, Malcolm
"All it does is force you to repeat the context on every function that uses the datatype" I think that's exactly what the original poster is complaining about. As a real- life example, consider data Graph a = Ord a => G [a] [[a]] My intention is that whenever I have a Graph a, I want to be able to use the Ord instance on a. So suppose I now define automorphisms :: (Ord a) => Graph a -> [Permutation a] On the basis of the "don't repeat yourself" principle, it seems redundant to have to specify the (Ord a) context here, since I already specified it in the data constructor for Graph a. So this is a proposal for a change to the language: don't require a context on a function if it is already implied by a context on a data type. (This would make even more sense for newtypes, where we know there is exactly one data constructor, so no possibility of different data constructors requiring different contexts.)

On Thu, Jun 9, 2011 at 09:46, DavidA
I think that's exactly what the original poster is complaining about. As a real- life example, consider data Graph a = Ord a => G [a] [[a]]
My intention is that whenever I have a Graph a, I want to be able to use the Ord instance on a.
So suppose I now define automorphisms :: (Ord a) => Graph a -> [Permutation a]
On the basis of the "don't repeat yourself" principle, it seems redundant to have to specify the (Ord a) context here, since I already specified it in the data constructor for Graph a.
So this is a proposal for a change to the language: don't require a context on a function if it is already implied by a context on a data type.
You can do this using GADTs. Like this: data Graph a where G :: Ord a => [a] -> [[a]] -> Graph a Now functions that pattern match on the 'G' constructor automatically have the Ord instance in scope, so it is no longer needed in the signature. Erik

Malcolm Wallace
The class context on the data constructor buys you nothing extra in terms of expressivity in the language. All it does is force you to repeat the context on every function that uses the datatype. For this reason, the language committee has decided that the feature will be removed in the next revision of Haskell.
Regards, Malcolm
Why not infer class contexts from type or data constructors, instead of ignoring them? Having to repeatedly state redundant type information is not a desirable state of affairs.
participants (5)
-
David Menendez
-
DavidA
-
Erik Hesselink
-
Guy
-
Malcolm Wallace