{-# LANGUAGE PolyKinds #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} -- Necessary for correct type for @setField@ {-# LANGUAGE AllowAmbiguousTypes #-} -- | Provide @Prelude@-like environment when using @RebindableSyntax@ -- -- If you want to use @large-records@ with 'OverloadedRecordDot' and -- 'OverloadedRecordUpdate', you need to enable the @RebindableSyntax@ language -- extension. You can then import this module to get a standard environment -- back, with one exception; see 'getField' for details. module Data.Record.Overloading ( module Prelude , Control.Arrow.app , Control.Arrow.arr , Control.Arrow.first , Control.Arrow.loop , (Control.Arrow.>>>) , (Control.Arrow.|||) , Data.String.fromString , GHC.OverloadedLabels.fromLabel -- * New definitions , ifThenElse , getField , setField ) where import qualified Control.Arrow import qualified Data.String import qualified GHC.OverloadedLabels import qualified GHC.Records.Compat {------------------------------------------------------------------------------- Other exports -------------------------------------------------------------------------------} ifThenElse :: Bool -> a -> a -> a ifThenElse b x y = if b then x else y -- | Get record field -- -- This is /NOT/ the standard @getField@ from "GHC.Records", but is instead -- defined in terms of "GHC.Records.Compat.HasField". As a consequence we do not -- currently support @OverloadedRecordDot@ without @RebindableSyntax@. -- (For ghc 9.2 and 9.4 @RebindableSyntax@ is required /anyway/ when using -- @OverloadedRecordUpdate@, so this is less of a limitation than it might -- seem.) -- -- Unfortunately, we /cannot/ currently support 'GHC.Records.HasField'; in the -- remainder of this comment we explain why. Consider a record such as -- -- > {-# ANN type Person largeRecord #-} -- > data Person = Person { name :: String } -- -- The internal representation of this record generated by @large-records@ -- looks something like this: -- -- > data Person = forall a. a ~ String => Person { name :: a } -- -- This representation prevents ghc from generating record accessors, whilst -- at the same time still making it possible to define and pattern match on -- records in the normal way. Unfortunately, although GHC does not generate -- a 'HasField' instance for such a record, it /also/ prevents us from -- defining our own: -- -- If a field has a higher-rank or existential type, the corresponding -- HasField constraint will not be solved automatically (as described above), -- but in the interests of simplicity we do not permit users to define their -- own instances either. -- -- -- -- There is a proposal to change this -- (), -- but for now we instead rely on 'GHC.Records.Compat.HasField', for which no -- such restrictions exist. getField :: forall x r a. GHC.Records.Compat.HasField x r a => r -> a getField = snd . GHC.Records.Compat.hasField @x setField :: forall x r a. GHC.Records.Compat.HasField x r a => r -> a -> r setField = fst . GHC.Records.Compat.hasField @x