packages feed

record-hasfield-1.0.1: src/GHC/Records/Extra.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}

{- | Extensions over a future version of "GHC.Records".
  Provides the function 'modifyField' plus the orphan instances:

* @HasField \'(x1,x2)@ for selecting first the @x1@ field, then the @x2@ field.
  Available for @()@ and tuples up to arity 5.

* @HasField \"_1\" (a,b) a@ for selecting the first compomnent of a pair,
  plus similarly for all fields up of all tuples up to arity 5.

  Using these functions together you get:

> modifyField @'("_1","_2") negate ((1,2),3,4,5) == ((1,-2),3,4,5)
-}
module GHC.Records.Extra (
    module GHC.Records.Compat,
    modifyField,
) where

import GHC.Records.Compat

-- | Modify a field in a record.
modifyField :: forall x r a. (HasField x r a) => r -> (a -> a) -> r
modifyField r f = gen $ f val
  where
    (gen, val) = hasField @x r

instance HasField '() a a where
    hasField r = (id, r)

instance (a1 ~ r2, HasField x1 r1 a1, HasField x2 r2 a2) => HasField '(x1, x2) r1 a2 where
    hasField r = (gen1 . gen2, val2)
      where
        (gen1, val1) = hasField @x1 r
        (gen2, val2) = hasField @x2 val1

instance
    (a1 ~ r2, a2 ~ r3, HasField x1 r1 a1, HasField x2 r2 a2, HasField x3 r3 a3) =>
    HasField '(x1, x2, x3) r1 a3
    where
    hasField = hasField @'(x1, '(x2, x3))

instance
    (a1 ~ r2, a2 ~ r3, a3 ~ r4, HasField x1 r1 a1, HasField x2 r2 a2, HasField x3 r3 a3, HasField x4 r4 a4) =>
    HasField '(x1, x2, x3, x4) r1 a4
    where
    hasField = hasField @'(x1, '(x2, x3, x4))

instance
    (a1 ~ r2, a2 ~ r3, a3 ~ r4, a4 ~ r5, HasField x1 r1 a1, HasField x2 r2 a2, HasField x3 r3 a3, HasField x4 r4 a4, HasField x5 r5 a5) =>
    HasField '(x1, x2, x3, x4, x5) r1 a5
    where
    hasField = hasField @'(x1, '(x2, x3, x4, x5))

instance HasField "_1" (a, b) a where
    hasField (a, b) = ((,b), a)
instance HasField "_2" (a, b) b where
    hasField (a, b) = ((a,), b)

instance HasField "_1" (a, b, c) a where
    hasField (a, b, c) = ((,b,c), a)
instance HasField "_2" (a, b, c) b where
    hasField (a, b, c) = ((a,,c), b)
instance HasField "_3" (a, b, c) c where
    hasField (a, b, c) = ((a,b,), c)

instance HasField "_1" (a, b, c, d) a where
    hasField (a, b, c, d) = ((,b,c,d), a)
instance HasField "_2" (a, b, c, d) b where
    hasField (a, b, c, d) = ((a,,c,d), b)
instance HasField "_3" (a, b, c, d) c where
    hasField (a, b, c, d) = ((a,b,,d), c)
instance HasField "_4" (a, b, c, d) d where
    hasField (a, b, c, d) = ((a,b,c,), d)

instance HasField "_1" (a, b, c, d, e) a where
    hasField (a, b, c, d, e) = ((,b,c,d,e), a)
instance HasField "_2" (a, b, c, d, e) b where
    hasField (a, b, c, d, e) = ((a,,c,d,e), b)
instance HasField "_3" (a, b, c, d, e) c where
    hasField (a, b, c, d, e) = ((a,b,,d,e), c)
instance HasField "_4" (a, b, c, d, e) d where
    hasField (a, b, c, d, e) = ((a,b,c,,e), d)
instance HasField "_5" (a, b, c, d, e) e where
    hasField (a, b, c, d, e) = ((a,b,c,d,), e)