Skip to content

Instantly share code, notes, and snippets.

@sjshuck
Last active February 15, 2026 04:23
Show Gist options
  • Select an option

  • Save sjshuck/0795bb43f174d487c465ba1c216d8727 to your computer and use it in GitHub Desktop.

Select an option

Save sjshuck/0795bb43f174d487c465ba1c216d8727 to your computer and use it in GitHub Desktop.
Data.Tuple.Index
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Tuple.Index (
FieldIndex(..),
ith,
updateIth,
) where
import Data.Kind (Constraint, Type)
import GHC.TypeLits (Nat)
#if defined(LENS)
import Control.Lens
#else
import Lens.Micro
import Lens.Micro.Extras (view)
import Lens.Micro.Internal
#endif
class FieldIndex (i :: Nat) where
type FieldByIndex i :: Type -> Type -> Type -> Type -> Constraint
_i :: (FieldByIndex i s t a b) => Lens s t a b
instance FieldIndex 1 where type FieldByIndex 1 = Field1; _i = _1
instance FieldIndex 2 where type FieldByIndex 2 = Field2; _i = _2
instance FieldIndex 3 where type FieldByIndex 3 = Field3; _i = _3
instance FieldIndex 4 where type FieldByIndex 4 = Field4; _i = _4
instance FieldIndex 5 where type FieldByIndex 5 = Field5; _i = _5
#if defined(LENS)
instance FieldIndex 6 where type FieldByIndex 6 = Field6; _i = _6
instance FieldIndex 7 where type FieldByIndex 7 = Field7; _i = _7
instance FieldIndex 8 where type FieldByIndex 8 = Field8; _i = _8
instance FieldIndex 9 where type FieldByIndex 9 = Field9; _i = _9
instance FieldIndex 10 where type FieldByIndex 10 = Field10; _i = _10
instance FieldIndex 11 where type FieldByIndex 11 = Field11; _i = _11
instance FieldIndex 12 where type FieldByIndex 12 = Field12; _i = _12
instance FieldIndex 13 where type FieldByIndex 13 = Field13; _i = _13
instance FieldIndex 14 where type FieldByIndex 14 = Field14; _i = _14
instance FieldIndex 15 where type FieldByIndex 15 = Field15; _i = _15
instance FieldIndex 16 where type FieldByIndex 16 = Field16; _i = _16
instance FieldIndex 17 where type FieldByIndex 17 = Field17; _i = _17
instance FieldIndex 18 where type FieldByIndex 18 = Field18; _i = _18
instance FieldIndex 19 where type FieldByIndex 19 = Field19; _i = _19
#endif
-- | Get the @i@th field of a tuple (or @Field@_n_ instance). Like `fst` or
-- `snd`.
--
-- > ith @3 (True, "Hello", 'x', Nothing) = 'x'
ith :: forall i s a. (FieldIndex i, FieldByIndex i s s a a) => s -> a
ith = view $ _i @i
-- | Modify the @i@th field of a tuple (or @Field@_n_ instance), possibly
-- changing its type. Like `first` or `second`.
--
-- > updateIth @3 ord (True, "Hello", 'x', Nothing) = (True, "Hello", 120, Nothing)
updateIth :: forall i s t a b. (FieldIndex i, FieldByIndex i s t a b) =>
(a -> b) -> s -> t
updateIth = over $ _i @i
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment