# How to define Normal for new "data types"

In Mathematica 9 and earlier, one of the points under "Details"/"More Information" section for the function Normal was (this is gone after version 10):

I have defined my own "data types" and would like to define Normal for them to be converted to normal expressions. How do I make this definition? (undocumented functionality for an efficient answer is encouraged)

## Example

Here is a "data type" called FractionSum, and it is a data structure containing a list of three items:

expr = FractionSum[{Item1 :> a, Item2 :> b, Item3 :> c}]


Then I would like the following behavior:

expr // Normal


1/a + 1/(a+b) + 1/(a+b+c)

• Are you intending to self-answer? Dec 23, 2016 at 0:34
• @Mr.Wizard No, I am asking sincerely. Do you have an answer? Dec 23, 2016 at 0:34
• Would you please tell me the ways in which my present answer is lacking that are important to you, so I can try to improve it if i have time? Mar 18, 2017 at 11:23
• @Mr.Wizard So sorry; by starting a bounty I didn't mean to snub your answer, which I think is very good. I am looking to see if there is a proper way to do it (as the older documentation suggests) without hacking or modifying built-in functions. Mar 18, 2017 at 17:11
• okay, no problem Mar 18, 2017 at 17:14

I may be overlooking a deeper aspect of this question but a quick and dirty UpSetDelayed definition appears to work:

Normal[FractionSum[rules : {__}]] ^:=
1/Item1 + 1/(Item1 + Item2) + 1/(Item1 + Item2 + Item3) /. rules

expr = FractionSum[{Item1 :> a, Item2 :> b, Item3 :> c}]

expr // Normal

1/a + 1/(a + b) + 1/(a + b + c)


This doesn't work with foo[expr] // Normal however (it does not match) so maybe:

Unprotect[Normal]

Normal[x_ /; ! FreeQ[Unevaluated@x, _FractionSum]] :=
Normal[
x /. FractionSum[rules : {__}] :>
(1/Item1 + 1/(Item1 + Item2) + 1/(Item1 + Item2 + Item3) /. rules)
]

Protect[Normal]


This still is not equivalent within held expression as described in the now-corrected Usage note section of Is there a way to control which special forms Normal converts? I shall continue to contemplate how this might be improved along with Leonid's admonition about modifying a System function in this way.

• Why not TagSetDelayed? It is usually cleaner than UpSetDelayed (although in this particular case it doesn't matter). Also, why should it work on foo[expr]? I don't see any reason to request or expect that. And, I would really avoid redefining Normal like that (via DownValues) - it may have many undesired consequences. Dec 23, 2016 at 2:42
• @LeonidShifrin To be clear, I want Normal to act on my "data type" just as it acts on built-in ones. This means it should work on foo[expr]. Dec 23, 2016 at 2:45
• @Leonid (1) ^:= makes definitions for all heads at level one but there is only one head here so I would argue that ^:= is cleaner if a little less explicit. (2) foo[SparseArray[{1}]] // Normal (3) I acknowledge that redefining any System function may have undesired consequences but I don't see why this one would be especially dangerous. Could you be more specific? edit I see that the way I wrote my code could lead to an infinite loop but that's a somewhat separate issue. Dec 23, 2016 at 2:45
• @Mr.Wizard (1) I view TagSetDelayed as a cleaner method precisely because it is more selective, so you always explicitly specify the symbol to which the rule is attached. I think this is good. (2) I didn't know about this, but actually I think this particular behavior / design choice was / is bad design. Allowing Normal to have non-local effects and going through expressions is just bad. (3) Normal is a pretty popular function. As such, it is called often enough in various parts of the system. As a rule, redefining such functions is bad, because you can't anticipate the consequences. Dec 23, 2016 at 10:16
• @Leonid (1) I guess I'll just agree to disagree, mindful of the fact that at least 80% of the time I end up agreeing with you later. Do you presently use UpSet for anything? (2) Quite a surprise! I could certainly see the value of adding a function that only operates directly but having Normal operate within expressions is very useful and I make use of that with some regularity. But you have made me look at Normal again with new eyes and I see that some of my past beliefs were wrong! Quantity will disregard Hold attributes which I had convinced myself it respected. Dec 23, 2016 at 18:28

using TagSetDelayed as pointed by @J.M. and @Leonid

FractionSum /: Normal[FractionSum[{patt : RuleDelayed[_, _Symbol] ..}]] :=
With[{sym = {patt}[[All, 2]]},
Plus @@ (Power[#, -1] &@Table[First@ListCorrelate[ConstantArray[1, i], sym],
{i, Length@sym}])]

FractionSum[{Item1 :> a, Item2 :> b, Item3 :> c}] // Normal

(* 1/a + 1/(a + b) + 1/(a + b + c) *)

• What I actually had in mind when using TagSetDelayed[] was something like FractionSum /: Normal[FractionSum[{patt : RuleDelayed[_, _Symbol] ..}]] := (* stuff *)... Mar 20, 2017 at 3:28
• @J.M. thanks ! edited Mar 20, 2017 at 3:39