Say I have something silly like this:
data SomeType
= Unary Int
| Associative SomeType
| Binary SomeType SomeType
some_func :: SomeType -> Int
some_func s =
case s of
Unary n -> n
Associative s1 -> some_func s1
Binary s1 s2 -> some_func s1 + some_func s2
Here some_func will look through all SomeTypes in a given SomeType and sum up the Ints of all Unary data constructors. SomeType is a recursive data type.
In these pattern matches I’m repeating some_func s1. Is there a way to use @, when, let or anything else to declare sf1 = some_func s1 and use it in both? Something like this:
data SomeType
= Unary Int
| Associative SomeType
| Binary SomeType SomeType
some_func :: SomeType -> Int
some_func s =
case s of
Unary n -> n
Associative s1 -> sf1
Binary s1 s2 -> sf1 + sf2
where
sf1 = some_func s1
sf2 = some_func s2
The problem here is that s1 and s2 are only known in the block after -> and sf1 can’t be calculated.
Abuse record syntax!
Note that different constructors of the same type are allowed to have the same named fields in their records. Laziness prevents you from erroring on
sf2if you go down theAssociativebranch.