Hi all,
I’m trying to figure out a way to dispatch functions on the field names of a record. The case_
function in Data.Variant
modules is almost exactly what I am looking for, since the exhaustive match requirement can catch a lot of problems at compile. In the example in the documentation, we have to list the specific field names in the types (like the function f
in the snippet below).
That works, but if I add or remove types from the record, I would have to make sure I make the corresponding change to all the type signatures for all the function that use case_
. Instead, I’m trying to figure out a type constructor where you can pass in a record type and have it spit out the appropriate variant type (something like function g
):
import Data.Variant (Variant, on, case_)
import Data.Symbol (SProxy(..), class IsSymbol)
import Data.Newtype (class Newtype)
import Prim.Row (class Cons)
newtype Params = Params { phase :: Int, voltage :: Number }
derive instance paramsNewtype :: Newtype Params _
f :: Variant (phase :: Unit, voltage :: Unit) -> String
f = case_
# on (SProxy :: SProxy "phase") (const "Dispatch phase...")
# on (SProxy :: SProxy "voltage") (const "Dispatch voltage...")
type ParamVariant p = forall sym fields tail.
IsSymbol sym
=> Newtype p (Record fields)
=> Cons sym Unit tail fields
=> Variant fields
g :: ParamVariant Params -> String
g = case_
# on (SProxy :: SProxy "phase") (const "Dispatch phase...")
# on (SProxy :: SProxy "voltage") (const "Dispatch voltage...")
The compiler complains with:
Could not match constrained type
IsSymbol sym0 => Newtype Params (Record fields1) => Cons sym0 Unit tail2 fields1 => Variant
fields1
with type
Variant t3
Can anyone give me a pointer on this? Please let me know if the question needs more elaboration.
Thanks!