Make `huddleRule`, `huddleGroup` and `huddleGRule` only return the body of the definition
Currently huddleRule, huddleGroup and huddleGRule methods return the entire defnition, e.g.
instance Era era => HuddleRule "epoch" era where
huddleRule _ = "epoch" =:= VUInt `sized` (8 :: Word64)
But we have access to the name of the rule at the type level, so I suggest to change huddleRule :: Proxy era -> Rule to huddleRuleBody :: Proxy era -> Type0
and then define huddleRule as a top-level function like so:
huddleRule :: forall (rule :: Symbol) era. (HuddleRule rule era, KnownSymbol rule) => Proxy era -> Rule
huddleRule era = symbolVal (Proxy @rule) =:= huddleRuleBody era
A similar approach can be taken for huddleGroup and huddleGRule. This approach will ensure that the name of the rule in the CDDL matches the rule in the instance, potentially saving us from future headaches.
On a second thought, the new version of cuddle also stores the comments and custom generators in the Rule, so the method would have to provide all of that extra information as well. I think I might change the definition of Rule to newtype Rule = Rule (Named RuleBody) at some point in the future and then RuleBody would contain the extra information. Currently Type0 can't have custom generators on its own.
the new version of cuddle also stores the comments and custom generators in the Rule
Not necessarily. We could add comment and custom generator to the HuddleRule type class, eg:
instance Era era => HuddleRule "epoch" era where
huddleRuleBody _ = VUInt `sized` (8 :: Word64)
huddleRuleComment _ = comment "Epoch number"
huddleRuleGenerator _ = Nothing
Then huddleRule becomes:
huddleRule :: forall (rule :: Symbol) era. (HuddleRule rule era, KnownSymbol rule) => Proxy era -> Rule
huddleRule era =
comment (huddleRuleComment @rule era)
$ maybe withGenerator id (huddleRuleGenerator @rule era)
$ symbolVal (Proxy @rule) =:= huddleRuleBody era
The original suggestion does not type-check because Type0 has many inhabitants, and in my limited understanding I could come up with two potential solutions: either something like class IsType0 r => HuddleRule name era | name era -> r or simply class IsType0 r => HuddleRule name era r, but @lehins suggested a better approach keeping the typeclass head unchanged while adding another Proxy to the huddleRuleNamed typeclass function:
class (KnownSymbol name, Era era) => HuddleRule (name :: Symbol) era where
huddleRule :: Proxy era -> Rule
huddleRuleNamed :: Proxy name -> Proxy era -> Rule
class (KnownSymbol name, Era era) => HuddleGroup (name :: Symbol) era where
huddleGroup :: Proxy era -> Named Group
huddleGroupNamed :: Proxy name -> Proxy era -> Named Group
class (KnownSymbol name, Era era) => HuddleGRule (name :: Symbol) era where
huddleGRule :: Proxy era -> GRuleDef
huddleGRuleNamed :: Proxy name -> Proxy era -> GRuleDef
class (KnownSymbol name, Era era) => HuddleRule1 (name :: Symbol) era where
huddleRule1 :: IsType0 a => Proxy era -> a -> GRuleCall
huddleRule1Named :: IsType0 a => Proxy name -> Proxy era -> a -> GRuleCall
huddleRule :: forall name era. HuddleRule name era => Proxy era -> Rule
huddleRule = huddleRuleNamed (Proxy @name)
huddleGroup :: forall name era. HuddleGroup name era => Proxy era -> Named Group
huddleGroup = huddleGroupNamed (Proxy @name)
huddleGRule :: forall name era. HuddleGRule name era => Proxy era -> GRuleDef
huddleGRule = huddleGRuleNamed (Proxy @name)
huddleRule1 :: forall name era a. (HuddleRule1 name era, IsType0 a) => Proxy era -> a -> GRuleCall
huddleRule1 = huddleRule1Named (Proxy @name)
(=.=) :: (KnownSymbol name, IsType0 t) => Proxy (name :: Symbol) -> t -> Rule
(=.=) pname t = T.pack (symbolVal pname) =:= t
infixr 0 =.=
(=.~) :: KnownSymbol name => Proxy (name :: Symbol) -> Group -> Named Group
(=.~) pname group = T.pack (symbolVal pname) =:~ group
infixr 0 =.~
@aniketd did you try with toType0?
class (KnownSymbol name, Era era) => HuddleRule (name :: Symbol) era where
huddleRuleBody :: Proxy era -> Type0
instance Era era => HuddleRule "epoch" era where
huddleRuleBody _ = toType0 (VUInt `sized` (8 :: Word64))