I’m trying to write HTML form helpers where I’d like the call-sites to support both of the following use-cases:
data FormCtx obj = { ctxFieldNamePrefix :: !Text, ctxObject :: !obj }
data MyRecord = MyRecord { field1 :: !Text, field2 :: !Text } deriving (Generic)
-- USE-CASE #1
let ctx = FormCtx "MyRecord" obj
fieldNameFor @"field1" ctx
-- USE-CASE #2 -- with a (Maybe obj)
let ctx = FormCtx "MyRecord" (Just obj)
fieldNameFor @"field1" ctx
-- Implementation for fieldNameFor which works only
-- with `obj`, and not `Maybe obj`
fieldNameFor :: forall.k obj a . (KnownSymbol k, HasField k obj a) => FormCtx obj -> Text
fieldNameFor FormCtx {ctxFieldNamePrefix} = ctxFieldNamePrefix <> "[" <> (Text.pack $ symbolVal (Proxy @k)) <> "]"
I’ve tried defining a type-classs, called FieldNameFor
to be able to define overlapping instances for obj
and Maybe obj
but I’m unable to make it work with the KnownSymbol k, HasField k obj a
typeclass constrains that are required for getField
to work.