Search code examples
haskelllazy-evaluationsuppress-warnings

Create record with all fields undefined, without triggering warning


I'd like to create a value of a record type that can be pattern-matched, without filling any fields.

data Foo = MkFoo
    { field1 :: Int
    , field2 :: Bool
    }

fun :: Foo -> Bool
fun MkFoo{..} = True

bar :: Bool
bar = fun MkFoo{}

This works because all fields of the Foo passed to fun are undefined, and fun is lazy in them. Of course, fun undefined would fail, because fun pattern-matches on the record constructor MkFoo.

However, this causes a compiler warning:

• Fields of MkFoo not initialised: field1, field2

I would like to get rid of this warning for this specific instance. So I am not looking to turn off the warning in general (with -Wno-missing-fields). I am also not looking to change fun (I could just make the pattern matching on MkFoo irrefutable). I would also like to avoid having to write out all fields of MkFoo, as in

bar = fun MkFoo{ field1 = undefined, field2 = undefined }

Solution

  • As mentioned in the comments, one option is to use generics, either the vanilla version or a helper package like generics-sop:

    {-# LANGUAGE DeriveAnyClass #-}
    {-# LANGUAGE DeriveGeneric #-}
    {-# LANGUAGE DerivingStrategies #-} -- derive stock, anyclass stuff
    {-# LANGUAGE ImportQualifiedPost #-} -- GHC >= 8.10
    import GHC.Generics
    import Generics.SOP qualified as SOP
    import Generics.SOP.NP (pure_NP)
    
    data Foo
      = MkFoo
          { field1 :: Int,
            field2 :: Bool
          }
      deriving stock (Generic)
      deriving anyclass (SOP.Generic)
    
    allundef :: Foo
    allundef = SOP.productTypeTo $ pure_NP undefined