Given a datatype
data Foo = Foo { one :: Int, two :: String } deriving (Show)
An incomplete expression passes typechecking — e.g.
foo :: Foo
foo = Foo { one = 5 }
main = print foo
Typechecks (emitting a warning about the incomplete record), then (obviously) crashes when the expression is encountered. Why does it pass? Without record syntax it doesn’t (i.e. bar = Foo 5 :: Foo).
The Haskell 2010 report says in section 3.15.2 Construction Using Field Labels
So it’s part of the language specification and a compiler must accept the code. All fields are initialized, just some are initialised with
undefined.is equivalent to
A nice compiler will warn you about it if you ask it to. If you want an error, make the fields strict.