{
  "$type": "site.standard.document",
  "bskyPostRef": {
    "cid": "bafyreibd6tzwpgzv7f2vpt24anuh5jb6mc7q3irlqniu2dlczq2askfep4",
    "uri": "at://did:plc:pi6woz4d47bkuws673w2il2r/app.bsky.feed.post/3mewhnk5hvwl2"
  },
  "path": "/t/minimal-processing-of-continued-fractions/13689#post_5",
  "publishedAt": "2026-02-15T11:37:44.000Z",
  "site": "https://discourse.haskell.org",
  "textContent": "I see it as a stateful fold with a stateful unfold inside it:\n\n\n    {-# LANGUAGE LambdaCase #-}\n    import Control.Monad.State.Lazy\n    import Data.Foldable\n    import Control.Monad\n\n    type Mat = (Integer, Integer, Integer, Integer)\n\n    matmul (a1, b1, c1, d1) (a2, b2, c2, d2) = (a1*a2 + b1*c2,\n                                                a1*b2 + b1*d2,\n                                                c1*a2 + d1*c2,\n                                                c1*b2 + d1*d2)\n\n    unfoldM :: Monad m => m (Maybe a) -> m [a]\n    unfoldM m = m >>= \\case\n      Nothing -> pure []\n      Just x -> (x :) <$> unfoldM m\n\n    cf_to_decimal :: [Integer] -> [Integer]\n    cf_to_decimal cf = evalState (foldr feed end cf) (1,0,0,1) where\n\n      emit :: State Mat (Maybe Integer)\n      emit = do\n        m@(a,b,c,d) <- get\n        let y0 = a `div` c\n            y1 = b `div` d\n        if c /= 0 && d /= 0 && y0 == y1 then do\n          put (matmul (10, -10*y0, 0, 1) m)\n          pure (Just y0)\n        else pure Nothing\n\n      feed :: Integer -> State Mat [Integer] -> State Mat [Integer]\n      feed x rest = do\n        modify (\\m -> matmul m (x,1,1,0))\n        (<>) <$> unfoldM emit <*> rest\n\n      end :: State Mat [Integer]\n      end = do\n       modify (\\(a,b,c,d) -> (a,a,c,c))\n       unfoldM $ do\n         (a,_,_,_) <- get\n         if a == 0 then pure Nothing else emit\n\n\nThis also gives you the laziness you want if you use the lazy state monad.",
  "title": "Minimal processing of continued fractions"
}