B. Zen
B. Zen

Reputation: 63

Why does adding a data type as constraint to type declaration result in matching error instead of a more correct error?

Or, putting in other terms, is there a case to add a constraint like described below?

Working code, with minimal type declaration for function f:

data ZeroPositive = Zero | Positive Int deriving Show
f :: [Int] -> [ZeroPositive]
f [] = []
f (0:xs) = Zero:(f xs)
f (x:xs) = (Positive x):(f xs)
main = putStrLn . show $ f [0,2]

result:

[Zero,Positive 2]

Broken code with useless constraint ZeroPositive:

data ZeroPositive = Zero | Positive Int deriving Show
f :: ZeroPositive => [Int] -> [ZeroPositive]
f [] = []
f (0:xs) = Zero:(f xs)
f (x:xs) = (Positive x):(f xs)
main = putStrLn . show $ f [0,2]

result:

  99.hs:3:7:
  Couldn't match expected type `ZeroPositive' with actual type `[t0]'
  In the pattern: []
  In an equation for `f': f [] = []

  99.hs:3:12:
  Couldn't match expected type `[Int] -> [ZeroPositive]'
          with actual type `[a0]'
  In the expression: []
  In an equation for `f': f [] = []

  ...

  99.hs:6:32:
  Couldn't match expected type `ZeroPositive' with actual type `[t0]'
  In the first argument of `f', namely `[0, 2]'
  In the second argument of `($)', namely `f [0, 2]'
  In the expression: putStrLn . show $ f [0, 2]

Upvotes: 4

Views: 67

Answers (2)

Ørjan Johansen
Ørjan Johansen

Reputation: 18189

This should be an error because ZeroPositive is a data type, not a class, so is not allowed as a constraint.

However the strange error message you are getting, is because you are using an old GHC version that had a bug (GHC 7.4 if I recall correctlyGHC 7.6, the one which got the ConstraintKinds extension generally working and therefore made => and -> allowed in more of the same places in the syntax) that made it treat => as -> if you put an actual data type instead of constraint to the left of it.

Upvotes: 5

dfeuer
dfeuer

Reputation: 48591

I don't understand the error you're getting; Ørjan Johansen's answer gives a plausible explanation. The real problem is this: any time a type signature indicates a => b, a is expected to be a constraint. In standard Haskell, that means that a looks like C t, where C is the name of a class and t is a type variable. In Glasgow Haskell, constraints can be a great deal richer. In any case, however, data and constraint are entirely different sorts of things (they have different types, in a general sense), so you simply can't use a datatype as a context.

Upvotes: 4

Related Questions