{-# LANGUAGE TemplateHaskell, DataKinds, TypeOperators, TypeFamilies, FlexibleContexts, OverloadedLabels #-} import Data.Extensible import Control.Lens type Stock c = Record '[ "name" >: String , "weight" >: Float , "price" >: c , "featured" >: Bool , "description" >: String , "quantity" >: Int] s0 :: Num c => Stock c s0 = #name @= "DA-192H" <: #weight @= 260 <: #price @= 120 <: #featured @= True <: #description @= "High-quality (24bit 192kHz), lightweight portable DAC" <: #quantity @= 20 <: emptyRecord -- Use shrinkAssoc to permute elements s1 :: Num c => Stock c s1 = shrinkAssoc $ #name @= "HHP-150" <: #featured @= False <: #description @= "Premium wooden headphone" <: #price @= 330 <: #quantity @= 55 <: #weight @= 200 <: emptyRecord -- If "quantity" is missing, -- Couldn't match type ‘Missing "quantity"’ with ‘Expecting one’ -- -- If there are duplicate "quantity", -- Couldn't match type ‘Ambiguous "quantity"’ with ‘Expecting one’ printSummary :: (Associate "name" String s, Associate "description" String s) => Record s -> IO () printSummary s = putStrLn $ view #name s ++ ": " ++ view #description s