Skip to content

Instantly share code, notes, and snippets.

@danidiaz
Last active April 7, 2020 16:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danidiaz/62df544a2879ccaa2fa7b2cdca6db394 to your computer and use it in GitHub Desktop.
Save danidiaz/62df544a2879ccaa2fa7b2cdca6db394 to your computer and use it in GitHub Desktop.
Remember this once RecordDotSyntax lands in GHC
-- see also https://stackoverflow.com/questions/61079836/why-isnt-the-constraint-trick-working-in-this-manually-defined-hasfield-insta
{-# LANGUAGE DataKinds, PolyKinds, FlexibleInstances, UndecidableInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE Rank2Types #-} -- for Into, otherwise unnecessary
{-# LANGUAGE StandaloneKindSignatures #-}
module Main where
import Control.Lens
import GHC.Records
import Data.Kind
type Glass :: Type -> Type
data Glass r = Glass -- just a dumb proxy
class Glassy r where
the :: Glass r
instance Glassy x where
the = Glass
instance HasField k r v => HasField k (Glass r) (Into r v) where
getField _ = Into (to (getField @k))
-- ReifiedGetter / runGetter would work as well
newtype Into s a = Into { into :: Getter s a }
data Person = Person { name :: String, age :: Int }
main :: IO ()
main = do
print $ Person "foo" 0 ^. into (getField @"name" the)
print $ Person "foo" 0 ^. into (getField @"age" the)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment