{
"$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"
}