With Haskell 98 decls, the whole datatype must be either newtype or data. But data families can have a mix of newtype instance, data instance. Does that mean that being newtype is a property of the data constructor rather than the datatype? Could there be a Haskell with something like:
data Foo a = MkFoo1 Int a
| MkFoo2 Bool a
| newtype MkFoo3 a
I know I can't write the following, but why/what goes wrong?:
data family Bar a
newtype instance Bar (Maybe Int) = MkBar1 (Maybe Int)
-- MkBar1 :: (Maybe Int) -> Bar (Maybe Int), see below
newtype instance Bar [Char] = MkBar2 [Char]
data instance Bar [Bool] where
MkBar3 :: Int -> Bool -> Bar [Bool]
-- can't be a newtype because of the existential Int
-- we're OK up to here mixing newtypes and data/GADT
data instance Bar [a] where
MkBar4 :: Num a => a -> Bar [a]
-- can't be a newtype because of the Num a =>
I can't write that because the instance head Bar [a] overlaps the two heads for MkBar2, MkBar3. Then I could fix that by moving those two constructor decls inside the where ... for Bar [a]. But then MkBar2 becomes a GADT (because it's result type is not Bar [a]), so can't be a newtype.
Then is being a newtype a property of the result type, rather than of the constructor? But consider the type inferred for newtype instance MkBar1 above. I can't write a top-level newtype with the same type
newtype Baz a where
MkBaz :: (Maybe Int) -> Baz (Maybe Int)
-- Error: A newtype constructor must have a return type of form T a1 ... an
Huh? MkBar1 is a newtype constructor whose type is not of that form.
If possible, please explain without diving into talk of roles: I've tried to understand them; it just makes my head hurt. Talk in terms of constructing and pattern-matching on those constructors.
newtypeis to use the same runtime representation as some other type (that is, with no wrappers), but if there are other cases to the type, that clearly isn’t possible. - Alexis KingBar a. "The whole point of a newtype ..., but if there are other cases to the type, that clearly isn’t possible. "Bar (Maybe Int),Bar [Char]are other cases of to the type, andnewtypeis possible -- until it gets tangled up withBar [a]. - AntCF, then surely you would not say thatF IntandF Boolmust be the same type, hm? The point is that GHC tracks that difference statically. It does not statically track the difference between different constructors (which is often frustrating to novice Haskellers, who regularly ask questions like “how can I have a type that isTbut restricted to exclude data constructorC,” to which the only answer is “define a new data type”). - Alexis KingBar a." is not precise. Try it yourself and see: make a data family with at least two instances, then writefoo :: Bar aand try to definefoowithout usingundefined. You'll find it's not possible! - Daniel Wagner