79675739

Date: 2025-06-23 06:51:50
Score: 0.5
Natty:
Report link

As @Li-yaoXia pointed out, you need a recursion point at each constructor you want to analyze. My initial definition of Stmt was incorrect because the `SAssign` constructor that models variable binding was a "leaf".

This is a better definition that actually models nested variable scopes:

data Stmt a = SAssign Id (Stmt a) -- id = ..; smt
          | SSeq [Stmt a] -- smt0; smt1; ..
          | SIf (Stmt a) (Stmt a) -- branching
          deriving (Show)

-- | base functor of Stmt
data StmtF a x = SAssignF Id x -- id = ...; smt
          | SSeqF [x] -- smt0; smt1; ..
          | SIfF x x
          deriving (Eq, Show, Functor, Foldable, Traversable)

instance Semigroup (Stmt a) where
  (<>) = undefined              -- we only need mempty
instance Monoid (Stmt a) where
  mempty = SSeq []
s0 :: Stmt a
s0 = SAssign 0 (SIf (SAssign 1 mempty) (SAssign 2 mempty))

gives us at last

λ>  scanCofree (<>) mempty $ binds s0
[0] :< SAssignF 0 ([0] :< SIfF ([0,1] :< SAssignF 1 ([0,1] :< SSeqF [])) ([0,2] :< SAssignF 2 ([0,2] :< SSeqF [])))
Reasons:
  • Long answer (-1):
  • Has code block (-0.5):
  • User mentioned (1): @Li-yaoXia
  • Self-answer (0.5):
  • Low reputation (0.5):
Posted by: ocramz