empty case, empty definitions

There are two separate parts I propose, the second one I'm less sure of, but they're somewhat related. 1. Allow empty case, i.e. "case some_variable of { }" (GHC ticket [1]). This adds consistency, it always causes a pattern-match error, and it is a sensible way to look at all the cases of types with no constructors (recall EmptyDataDecls will probably be in Haskell' [4]) -- especially for automatic tools (or programmers familiar with dependent types; GADTs have some of these effects :-)). Presumably, any time that some_variable could be non-bottom, GHC will warn about the incomplete patterns :-). 2. When a type signature for a function is given, allow to not define any patterns (GHC ticket [2]). The result of calling the function is a pattern match failure (presumably the source-location given for the match failure will be the location of the type-signature). This can also be useful for calling functions before implementing them, helping the type-checker help me do incremental work (again, obviously produces a warning if the function could possibly be non-bottom). However I can think of a few things this (proposal 2) could interfere with: 2.i. Implementing a class method, will you get the default if that method has a default? Actually it turns out to be forbidden... class C n where foo :: n -> n foo = id instance C Int where foo :: Int -> Int --even if we define foo here too, it's an error: --misplaced type signature (perhaps thanks to improved --error messages, thanks simonpj! [5]). --Anyway, I think type signatures ought to be allowed here. I propose to allow type-signatures in instances, which must be equivalent to the signature in the class declaration after the class's signature is specialized to the particular instance type(s). If such a type-signature is found, allow the function to be defined as normal, which includes, if there are no patterns, an error if proposal 2 isn't adopted, and a pattern-match failure if proposal 2 is adopted. (also it turns out that pattern bindings aren't allowed in instances, such as {instance C Int where (foo) = negate}, but I can't say I have a compelling use-case for that!:-)) 2.ii. It could interfere with another feature request of mine (though I'm not sure I want it anymore) (GHC ticket [3]) : I'd like it to be allowed to give a (possibly more restrictive?) type signature at the top level of a module, to a function imported unqualified. Obviously in this case I don't want the function to be treated as pattern-match failure; but I think we can tell the difference because the name is in-scope in this case. Luckily there is no negative interaction with my related proposal to simply allow multiple equivalent type-signatures anywhere one of them is allowed in a declaration-list. So actually, in summary I can't really see anything wrong with proposal 2, especially if my proposal under 2.i. is adopted. [1] http://hackage.haskell.org/trac/ghc/ticket/2431 [2] http://hackage.haskell.org/trac/ghc/ticket/393 [3] http://hackage.haskell.org/trac/ghc/ticket/1404 [4] http://hackage.haskell.org/trac/haskell-prime/wiki/EmptyDataDecls [5] http://hackage.haskell.org/trac/ghc/ticket/1310

Hi
1. Allow empty case, i.e. "case some_variable of { }" (GHC ticket [1]). This adds consistency, it always causes a pattern-match error, and it is a sensible way to look at all the cases of types with no constructors (recall EmptyDataDecls will probably be in Haskell' [4]) -- especially for automatic tools (or programmers familiar with dependent types; GADTs have some of these effects :-)). Presumably, any time that some_variable could be non-bottom, GHC will warn about the incomplete patterns :-).
Sounds good. Great for consistency and auto-generation of code.
2. When a type signature for a function is given, allow to not define any patterns (GHC ticket [2]). The result of calling the function is a pattern match failure (presumably the source-location given for the match failure will be the location of the type-signature). This can also be useful for calling functions before implementing them, helping the type-checker help me do incremental work (again, obviously produces a warning if the function could possibly be non-bottom).
Sounds bad. Consider: gray :: Color grey = newColor "#ccc" This fairly common style of bug now becomes perfectly valid Haskell, and if you always refer to "grey", you may never even have a clue that the bug is present. Thanks Neil

Neil Mitchell wrote:
Sounds bad. Consider:
gray :: Color grey = newColor "#ccc"
My rationale for typoes not being a problem (both your example, and the one Malcolm Wallace posted to the "empty case" ticket) is that GHC will give you a warning anyway (and that warning should be on by default). Should we be worrying about the situation being worse for other compilers that don't have good warning-systems (e.g. I don't think Hugs has warnings at all)? -Isaac

Hi,
Sounds bad. Consider:
gray :: Color grey = newColor "#ccc"
This fairly common style of bug now becomes perfectly valid Haskell, and if you always refer to "grey", you may never even have a clue that the bug is present.
I think the compiler should certainly give a warning that no equations are defined for a definition. It would be impossible to check for user typos! :) It does make me beg the question though: why do we want to define data types without any constructors? If we do opt for empty data declarations, then both general pattern matching and case expressions need to be able to cope with it for consistency. Regards, Chris

I'm with Neil on this. Suggestion 1 is great, whereas suggestion 2
just makes it easier to make mistakes, and that's not what we want.
On Fri, Aug 15, 2008 at 6:34 PM, Isaac Dupree
There are two separate parts I propose, the second one I'm less sure of, but they're somewhat related.
1. Allow empty case, i.e. "case some_variable of { }" (GHC ticket [1]). This adds consistency, it always causes a pattern-match error, and it is a sensible way to look at all the cases of types with no constructors (recall EmptyDataDecls will probably be in Haskell' [4]) -- especially for automatic tools (or programmers familiar with dependent types; GADTs have some of these effects :-)). Presumably, any time that some_variable could be non-bottom, GHC will warn about the incomplete patterns :-).
2. When a type signature for a function is given, allow to not define any patterns (GHC ticket [2]). The result of calling the function is a pattern match failure (presumably the source-location given for the match failure will be the location of the type-signature). This can also be useful for calling functions before implementing them, helping the type-checker help me do incremental work (again, obviously produces a warning if the function could possibly be non-bottom).
However I can think of a few things this (proposal 2) could interfere with: 2.i. Implementing a class method, will you get the default if that method has a default? Actually it turns out to be forbidden... class C n where foo :: n -> n foo = id instance C Int where foo :: Int -> Int --even if we define foo here too, it's an error: --misplaced type signature (perhaps thanks to improved --error messages, thanks simonpj! [5]). --Anyway, I think type signatures ought to be allowed here. I propose to allow type-signatures in instances, which must be equivalent to the signature in the class declaration after the class's signature is specialized to the particular instance type(s). If such a type-signature is found, allow the function to be defined as normal, which includes, if there are no patterns, an error if proposal 2 isn't adopted, and a pattern-match failure if proposal 2 is adopted. (also it turns out that pattern bindings aren't allowed in instances, such as {instance C Int where (foo) = negate}, but I can't say I have a compelling use-case for that!:-))
2.ii. It could interfere with another feature request of mine (though I'm not sure I want it anymore) (GHC ticket [3]) : I'd like it to be allowed to give a (possibly more restrictive?) type signature at the top level of a module, to a function imported unqualified. Obviously in this case I don't want the function to be treated as pattern-match failure; but I think we can tell the difference because the name is in-scope in this case. Luckily there is no negative interaction with my related proposal to simply allow multiple equivalent type-signatures anywhere one of them is allowed in a declaration-list.
So actually, in summary I can't really see anything wrong with proposal 2, especially if my proposal under 2.i. is adopted.
[1] http://hackage.haskell.org/trac/ghc/ticket/2431 [2] http://hackage.haskell.org/trac/ghc/ticket/393 [3] http://hackage.haskell.org/trac/ghc/ticket/1404 [4] http://hackage.haskell.org/trac/haskell-prime/wiki/EmptyDataDecls [5] http://hackage.haskell.org/trac/ghc/ticket/1310 _______________________________________________ Haskell-prime mailing list Haskell-prime@haskell.org http://www.haskell.org/mailman/listinfo/haskell-prime
participants (4)
-
C.M.Brown
-
Isaac Dupree
-
Lennart Augustsson
-
Neil Mitchell